`timescale 1ns / 1ps
`define YSYX210448_ZERO_WORD  64'h00000000_00000000
`define YSYX210448_ZERO_8     8'b00000000
`define YSYX210448_PC_START   64'h00000000_30000000  
`define YSYX210448_REG_BUS    63 : 0     
`define YSYX210448_AXI_ADDR_WIDTH      64
`define YSYX210448_AXI_DATA_WIDTH      64
`define YSYX210448_AXI_ID_WIDTH        4
`define YSYX210448_AXI_USER_WIDTH      1
`define YSYX210448_SIZE_B              2'b00
`define YSYX210448_SIZE_H              2'b01
`define YSYX210448_SIZE_W              2'b10
`define YSYX210448_SIZE_D              2'b11
`define YSYX210448_REQ_READ            1'b0
`define YSYX210448_REQ_WRITE            1'b1
`define YSYX210448_RISCV_PRIV_MODE_U    0
`define YSYX210448_RISCV_PRIV_MODE_S    1
`define YSYX210448_RISCV_PRIV_MODE_M   3
`define YSYX210448_W_STATE_IDLE        2'b00
`define YSYX210448_W_STATE_ADDR        2'b01
`define YSYX210448_W_STATE_WRITE       2'b10
`define YSYX210448_W_STATE_RESP        2'b11
`define YSYX210448_R_STATE_IDLE        2'b00
`define YSYX210448_R_STATE_ADDR        2'b01
`define YSYX210448_R_STATE_READ        2'b10
 

module ysyx_210448(
    input                               clock,
    input                               reset,
    input                               io_interrupt,


    input                               io_master_awready,
    input  [31:0]                       io_slave_awaddr,
    input                               io_slave_awvalid,
    input  [3:0]                        io_slave_awid,
    input  [7:0]                        io_slave_awlen,
    input  [2:0]                        io_slave_awsize,
    input  [1:0]                        io_slave_awburst,
    output                              io_slave_awready,
    output                              io_master_awvalid, 
    output [31:0]                       io_master_awaddr,
    output [3:0]                        io_master_awid,
    output [7:0]                        io_master_awlen,
    output [2:0]                        io_master_awsize,
    output [1:0]                        io_master_awburst,
    

    input                               io_master_wready,
    input                               io_slave_wvalid,
    input  [63:0]                       io_slave_wdata,
    input  [7:0]                        io_slave_wstrb,
    input                               io_slave_wlast,
    output                              io_slave_wready,
    output                              io_master_wvalid,
    output [63:0]                       io_master_wdata,
    output [7:0]                        io_master_wstrb,
    output                              io_master_wlast, 


    input                               io_slave_bready,
    input                               io_master_bvalid,
    input  [1:0]                        io_master_bresp,
    input  [3:0]                        io_master_bid,
    output                              io_slave_bvalid,
    output                              io_master_bready,
    output [1:0]                        io_slave_bresp,
    output [3:0]                        io_slave_bid,


    input                               io_master_arready,
    input                               io_slave_arvalid,
    input  [31:0]                       io_slave_araddr,
    input  [3:0]                        io_slave_arid,
    input  [7:0]                        io_slave_arlen,
    input  [2:0]                        io_slave_arsize,
    input  [1:0]                        io_slave_arburst,
    output                              io_slave_arready,
    output                              io_master_arvalid, 
    output [31:0]                       io_master_araddr,  
    output [3:0]                        io_master_arid,   
    output [7:0]                        io_master_arlen,   
    output [2:0]                        io_master_arsize,  
    output [1:0]                        io_master_arburst, 


    input                               io_slave_rready,
    input                               io_master_rvalid,
    input  [1:0]                        io_master_rresp,
    input  [63:0]                       io_master_rdata,
    input                               io_master_rlast, 
    input  [3:0]                        io_master_rid,
    output                              io_slave_rvalid,
    output                              io_master_rready,
    output [1:0]                        io_slave_rresp,
    output [63:0]                       io_slave_rdata, 
    output                              io_slave_rlast,    
    output [3:0]                        io_slave_rid
);

assign io_slave_rid=4'b0;
assign io_slave_rresp=2'b0;
assign io_slave_rlast=1'b0;
assign io_slave_rvalid=1'b0;
assign io_slave_wready=1'b0;
assign io_slave_bvalid=1'b0;
assign io_slave_bresp=2'b0;
assign io_slave_bid=4'b0;
assign io_slave_arready=1'b0;
assign io_slave_awready=1'b0;
assign io_slave_rdata=64'b0;



wire [63:0] top_axi_aw_addr_o;
wire [63:0] top_axi_ar_addr_o;
assign io_master_awaddr=top_axi_aw_addr_o[31:0];
assign io_master_araddr=top_axi_ar_addr_o[31:0];

//wire [2:0] top_exe_s1;
wire top_b_hs;
wire [63:0] top_mtime;
wire [63:0] top_mtimecmp;
wire [1:0] top_w_axi_size;
//wire top_mem_read;
wire top_w_req_i;
//wire top_w_req_i=top_mem_write;
wire top_r_req_i=1'b0;
wire top_axi_read_ready;
wire [63:0] top_axi_data_read;
wire  top_axi_read_valid;
wire [63:0] top_axi_read_addr;
wire [1:0] top_axi_size;
wire [63:0] top_axi_write_data;
wire [63:0] top_axi_write_addr;
wire [7:0] top_axi_write_mask;
wire [3:0] top_axi_r_id_o;
wire [3:0] top_axi_id;
wire [63:0] top_mem_read_data;
wire top_axi_mem_write;
//wire top_mem_write;
wire top_axi_r_hs_o;
wire [63:0] top_mtimecmp_data;
wire top_mtimecmp_open;
wire [63:0] top_mtime_data;
wire top_mtime_open;


    ysyx_210448_axi_rw ysyx_210448_u_axi_rw (
        .clock                          (clock),
        .reset                          (reset),

        .rw_valid_i                     (top_axi_read_valid),
        .rw_ready_o                     (top_axi_read_ready),
        .r_req_i                        (top_r_req_i),
        .w_req_i                        (top_w_req_i),
        .axi_read_id                    (top_axi_id),
        //.exe_s1                         (top_exe_s1),
        .mtime                          (top_mtime),
        .mtimecmp                       (top_mtimecmp),
        .data_read_o                    (top_axi_data_read),
        .data_write_i                   (top_axi_write_data),
        .rw_addr_i                      (top_axi_read_addr),
        .rw_size_i                      (top_axi_size),
        .w_axi_size                     (top_w_axi_size),
        //.mem_read                       (top_mem_read),
        .axi_write_valid                (top_axi_mem_write),
        .w_mem_mask                     (top_axi_write_mask),
        .w_mem_addr                     (top_axi_write_addr),
        .mtimecmp_data                  (top_mtimecmp_data),
        .mtimecmp_open                  (top_mtimecmp_open),
        .mtime_data                     (top_mtime_data),
        .mtime_open                     (top_mtime_open),

        .axi_aw_ready_i                 (io_master_awready),
        .axi_aw_valid_o                 (io_master_awvalid),
        .axi_aw_addr_o                  (top_axi_aw_addr_o),
        .axi_aw_id_o                    (io_master_awid),
        .axi_aw_len_o                   (io_master_awlen),
        .axi_aw_size_o                  (io_master_awsize),
        .axi_aw_burst_o                 (io_master_awburst),


        .axi_w_ready_i                  (io_master_wready),
        .axi_w_valid_o                  (io_master_wvalid),
        .axi_w_data_o                   (io_master_wdata),
        .axi_w_strb_o                   (io_master_wstrb),
        .axi_w_last_o                   (io_master_wlast),

        
        .axi_b_ready_o                  (io_master_bready),
        .axi_b_valid_i                  (io_master_bvalid),
        .axi_b_resp_i                   (io_master_bresp),
        .axi_b_id_i                     (io_master_bid),

        .axi_ar_ready_i                 (io_master_arready),
        .axi_ar_valid_o                 (io_master_arvalid),
        .axi_ar_addr_o                  (top_axi_ar_addr_o),
        .axi_ar_id_o                    (io_master_arid),
        .axi_ar_len_o                   (io_master_arlen),
        .axi_ar_size_o                  (io_master_arsize),
        .axi_ar_burst_o                 (io_master_arburst),
    

        .axi_r_ready_o                  (io_master_rready),
        .axi_r_valid_i                  (io_master_rvalid),
        .axi_r_resp_i                   (io_master_rresp),
        .axi_r_data_i                   (io_master_rdata),
        .axi_r_last_i                   (io_master_rlast),
        .axi_r_id_i                     (io_master_rid),
        .axi_r_id_o                     (top_axi_r_id_o),
        .mem_data_read                  (top_mem_read_data),
        .b_hs                           (top_b_hs),
        .axi_r_hs_o                     (top_axi_r_hs_o)
    );
    
    

    ysyx_210448_cpu ysyx_210448_CPU(
    .clock(clock),
    .reset(reset),
    //.exe_s1(top_exe_s1),
    .mtime(top_mtime),
    .mtimecmp(top_mtimecmp),
    .mtimecmp_data(top_mtimecmp_data),
    .mtimecmp_open(top_mtimecmp_open),
    .mtime_data(top_mtime_data),
    .mtime_open(top_mtime_open),
    .axi_r_id_i(top_axi_r_id_o),
    .axi_id(top_axi_id),
    //.mem_read(top_mem_read),
    .axi_read_ready(top_axi_read_ready),
    .axi_data_read(top_axi_data_read),
    .axi_read_valid(top_axi_read_valid),
    .axi_read_addr(top_axi_read_addr),
    .axi_size(top_axi_size),
    .w_axi_size(top_w_axi_size),
    .axi_write_data(top_axi_write_data),
    .axi_write_addr(top_axi_write_addr),
    .axi_mem_write(top_axi_mem_write),
    .mem_write(top_w_req_i),
    .axi_write_mask(top_axi_write_mask),
    .r_hs(top_axi_r_hs_o),
    .b_hs(top_b_hs),
    .r_data(top_mem_read_data)
    );


endmodule


module ysyx_210448_axi_rw # (
    //parameter RW_ADDR_WIDTH     = 64,
    parameter YSYX210448_AXI_DATA_WIDTH    = 64,
    //parameter RW_DATA_WIDTH     = 64,
    parameter YSYX210448_AXI_ADDR_WIDTH    = 64,
    parameter YSYX210448_AXI_ID_WIDTH      = 4,
    parameter YSYX210448_ALIGNED_WIDTH = 3,//$clog2(YSYX210448_AXI_DATA_WIDTH / 8);
    //parameter OFFSET_WIDTH  = 3,//$clog2(YSYX210448_AXI_DATA_WIDTH);
    //parameter AXI_SIZE      = 3,//$clog2(YSYX210448_AXI_DATA_WIDTH / 8);
    //parameter MASK_WIDTH    = 128,//YSYX210448_AXI_DATA_WIDTH * 2;
    parameter YSYX210448_TRANS_LEN     = 1,//RW_DATA_WIDTH / YSYX210448_AXI_DATA_WIDTH;
    parameter YSYX210448_BLOCK_TRANS   = YSYX210448_TRANS_LEN > 1 ? 1'b1 : 1'b0
)(
    input                               clock,
    input                               reset,

    input  [3:0]                        axi_read_id,
	  input                               rw_valid_i,
    input  [63:0]                       data_write_i,
    input  [YSYX210448_AXI_DATA_WIDTH-1:0]         rw_addr_i,
    input                               r_req_i,
    input                               w_req_i,
    //input  [2:0]                        exe_s1,
    //input                               mem_read,
    input  [1:0]                        rw_size_i,
    input  [63:0]                       mtime,
    input  [63:0]                       mtimecmp,
    input  [1:0]                        w_axi_size,
  	output                              rw_ready_o,
    output reg [63:0]                   data_read_o,
    input                               axi_write_valid,
    input  [7:0]                        w_mem_mask,
    input  [63:0]                       w_mem_addr,
    output [63:0]                       mtimecmp_data,
    output                              mtimecmp_open, 
    output [63:0]                       mtime_data,
    output                              mtime_open,              
//写地址信号
    input                               axi_aw_ready_i,//准备写入
    output                              axi_aw_valid_o,//写地址有效
    output [YSYX210448_AXI_ADDR_WIDTH-1:0]         axi_aw_addr_o,//写地址
    output [YSYX210448_AXI_ID_WIDTH-1:0]           axi_aw_id_o,//写地址id
    output [7:0]                        axi_aw_len_o,//burst长度
    output [2:0]                        axi_aw_size_o,//burst大小
    output [1:0]                        axi_aw_burst_o,//burst类型
//写数据信号
    input                               axi_w_ready_i,
    output                              axi_w_valid_o,
    output reg [YSYX210448_AXI_DATA_WIDTH-1:0]         axi_w_data_o,
    output [YSYX210448_AXI_DATA_WIDTH/8-1:0]       axi_w_strb_o,//写掩码。此信号指示哪些字节通道保存有效的数据。写数据总线的每8位都有一个写频闪位。
    output                              axi_w_last_o,//此信号表示写突发中的最后一次传输。
//写响应信号    
    output                              axi_b_ready_o,
    input                               axi_b_valid_i,
    input  [1:0]                        axi_b_resp_i,//写入响应。此信号表示写入事务处理的状态。
    input  [YSYX210448_AXI_ID_WIDTH-1:0]           axi_b_id_i,//响应ID标签。此信号是写响应的ID标记。
//读地址信号
    input                               axi_ar_ready_i,
    output                              axi_ar_valid_o,
    output [YSYX210448_AXI_ADDR_WIDTH-1:0]         axi_ar_addr_o,
    output [YSYX210448_AXI_ID_WIDTH-1:0]           axi_ar_id_o,//读地址id
    output [7:0]                        axi_ar_len_o,//burst长度
    output [2:0]                        axi_ar_size_o,//burst大小
    output [1:0]                        axi_ar_burst_o,//burst类型
//读数据信号   
    output                              axi_r_ready_o,
    input                               axi_r_valid_i,
    input  [1:0]                        axi_r_resp_i,//为每个读取事务处理发送的服务质量标识符。仅在AXI4中实现
    input  [YSYX210448_AXI_DATA_WIDTH-1:0]         axi_r_data_i,
    input                               axi_r_last_i,//此信号表示读取突发中的最后一次传输。
    input  [YSYX210448_AXI_ID_WIDTH-1:0]           axi_r_id_i,//读取ID标签。该信号是由从服务器生成的信号的读取数据组的识别标签。
    output reg [3:0]                        axi_r_id_o,
    output reg [63:0]                       mem_data_read,
    output                              b_hs,
    output reg                             axi_r_hs_o
);
    wire [3:0] axi_b_id=axi_b_id_i;
    wire r_hs;
    wire w_trans    = w_req_i == `YSYX210448_REQ_WRITE ;
    wire r_trans    = r_req_i == `YSYX210448_REQ_READ;
    wire w_valid    = w_trans;//rw_valid_i & 
    wire r_valid    = rw_valid_i & r_trans;
//握手成功信号
    wire aw_hs      = axi_aw_ready_i & axi_aw_valid_o;//写地址握手成功
    wire w_hs       = axi_w_ready_i  & axi_w_valid_o;//写数据握手成功
    assign b_hs       = axi_b_ready_o  & axi_b_valid_i;//写相应握手成功
    wire ar_hs      = axi_ar_ready_i & axi_ar_valid_o;//读地址握手成功
    assign r_hs       = axi_r_ready_o  & axi_r_valid_i;//读数据手成功

    wire w_done     = w_hs & axi_w_last_o;
    wire r_done     = r_hs & axi_r_last_i;
    //wire trans_done = w_trans ? b_hs : r_done;
    wire trans_done=r_done;
    
    // ------------------State Machine------------------
    //parameter [1:0] YSYX210448_W_STATE_IDLE = 2'b00, W_STATE_ADDR = 2'b01, W_STATE_WRITE = 2'b10, W_STATE_RESP = 2'b11;
    //parameter [1:0] R_STATE_IDLE = 2'b00, R_STATE_ADDR = 2'b01, R_STATE_READ  = 2'b10; 

    reg [1:0] w_state, r_state;
    wire w_stata_idle = w_state == `YSYX210448_W_STATE_IDLE, w_state_addr = w_state == `YSYX210448_W_STATE_ADDR, w_state_write = w_state == `YSYX210448_W_STATE_WRITE, w_state_resp = w_state == `YSYX210448_W_STATE_RESP;
    wire r_state_idle = r_state == `YSYX210448_R_STATE_IDLE, r_state_addr = r_state == `YSYX210448_R_STATE_ADDR, r_state_read  = r_state == `YSYX210448_R_STATE_READ;

    // Wirte State Machine
    always @(posedge clock) begin
        if (reset) begin
            w_state <= `YSYX210448_W_STATE_IDLE;
        end
        else begin
            if (w_valid) begin
                case (w_state)
                    `YSYX210448_W_STATE_IDLE:               w_state <= `YSYX210448_W_STATE_ADDR;
                    `YSYX210448_W_STATE_ADDR:  if (aw_hs)   w_state <= `YSYX210448_W_STATE_WRITE;
                    `YSYX210448_W_STATE_WRITE: if (w_done)  w_state <= `YSYX210448_W_STATE_RESP;
                    `YSYX210448_W_STATE_RESP:  if (b_hs)    w_state <= `YSYX210448_W_STATE_IDLE;
                endcase
            end
            
        end
    end

    // Read State Machine
    always @(posedge clock) begin
        if (reset) begin
            r_state <= `YSYX210448_R_STATE_IDLE;
        end
        else begin
            if (r_valid) begin
                case (r_state)
                    `YSYX210448_R_STATE_IDLE:                          r_state <= `YSYX210448_R_STATE_ADDR;
                    `YSYX210448_R_STATE_ADDR: if (ar_hs)               r_state <= `YSYX210448_R_STATE_READ;
                    `YSYX210448_R_STATE_READ: if (r_done)              r_state <= `YSYX210448_R_STATE_IDLE;
                    default:;
                endcase
            end
            else
            begin
              if(r_done)  r_state<=`YSYX210448_R_STATE_IDLE;
            end
        end
    end


   


    // ------------------Process Data------------------
    //数据处理

    //parameter ALIGNED_WIDTH = $clog2(YSYX210448_AXI_DATA_WIDTH / 8);
    //parameter OFFSET_WIDTH  = $clog2(YSYX210448_AXI_DATA_WIDTH);
    //parameter AXI_SIZE      = $clog2(YSYX210448_AXI_DATA_WIDTH / 8);
    //parameter MASK_WIDTH    = YSYX210448_AXI_DATA_WIDTH * 2;
    //parameter TRANS_LEN     = RW_DATA_WIDTH / YSYX210448_AXI_DATA_WIDTH;
    //parameter BLOCK_TRANS   = TRANS_LEN > 1 ? 1'b1 : 1'b0;

    wire aligned            = YSYX210448_BLOCK_TRANS | rw_addr_i[YSYX210448_ALIGNED_WIDTH-1:0] == 0;
    wire YSYX210448_SIZE_B             = rw_size_i == `YSYX210448_SIZE_B;
    wire YSYX210448_SIZE_H             = rw_size_i == `YSYX210448_SIZE_H;
    wire YSYX210448_SIZE_W             = rw_size_i == `YSYX210448_SIZE_W;
    wire YSYX210448_SIZE_D             = rw_size_i == `YSYX210448_SIZE_D;
    wire [3:0] addr_op1     = {{4-YSYX210448_ALIGNED_WIDTH{1'b0}}, rw_addr_i[YSYX210448_ALIGNED_WIDTH-1:0]};
    wire [3:0] addr_op2     = ({4{YSYX210448_SIZE_B}} & {4'b0})
                                | ({4{YSYX210448_SIZE_H}} & {4'b1})
                                | ({4{YSYX210448_SIZE_W}} & {4'b11})
                                | ({4{YSYX210448_SIZE_D}} & {4'b111})
                                ;
    wire [3:0] addr_end     = addr_op1 + addr_op2;
    wire overstep           = addr_end[3:YSYX210448_ALIGNED_WIDTH] != 0;

    wire [7:0] axi_len      = aligned ? YSYX210448_TRANS_LEN - 1 : {{7{1'b0}}, overstep};//8'b0;//
    //wire [2:0] axi_size     = AXI_SIZE[2:0];
    
    wire [YSYX210448_AXI_ADDR_WIDTH-1:0] axi_addr          = rw_addr_i;//{rw_addr_i[YSYX210448_AXI_ADDR_WIDTH-1:ALIGNED_WIDTH], {ALIGNED_WIDTH{1'b0}}};//rw_addr_i;//(mem_read)?((r_hs&&(axi_r_id_i==4'b0001))?rw_addr_i
                                                  //:{rw_addr_i[YSYX210448_AXI_ADDR_WIDTH-1:ALIGNED_WIDTH], {ALIGNED_WIDTH{1'b0}}}):rw_addr_i;
    //wire [OFFSET_WIDTH-1:0] aligned_offset_l    = {{OFFSET_WIDTH-ALIGNED_WIDTH{1'b0}}, {rw_addr_i[ALIGNED_WIDTH-1:0]}} << 3;
    //wire [OFFSET_WIDTH-1:0] aligned_offset_h    = {6{1'b1}}- aligned_offset_l;
    /*wire [MASK_WIDTH-1:0] mask                  = (({MASK_WIDTH{YSYX210448_SIZE_B}} & {{MASK_WIDTH-8{1'b0}}, 8'hff})
                                                    | ({MASK_WIDTH{YSYX210448_SIZE_H}} & {{MASK_WIDTH-16{1'b0}}, 16'hffff})
                                                    | ({MASK_WIDTH{YSYX210448_SIZE_W}} & {{MASK_WIDTH-32{1'b0}}, 32'hffffffff})
                                                    | ({MASK_WIDTH{YSYX210448_SIZE_D}} & {{MASK_WIDTH-64{1'b0}}, 64'hffffffff_ffffffff})
                                                    ) << aligned_offset_l;
                                                    */
    //wire [YSYX210448_AXI_DATA_WIDTH-1:0] mask_l            = mask[YSYX210448_AXI_DATA_WIDTH-1:0];
    //wire [YSYX210448_AXI_DATA_WIDTH-1:0] mask_h            = mask[MASK_WIDTH-1:YSYX210448_AXI_DATA_WIDTH];

    wire [YSYX210448_AXI_ID_WIDTH-1:0] axi_id              = axi_read_id;
    //write
    wire [YSYX210448_AXI_ADDR_WIDTH-1:0] axi_write_addr          = w_mem_addr;//{w_mem_addr[YSYX210448_AXI_ADDR_WIDTH-1:ALIGNED_WIDTH], {ALIGNED_WIDTH{1'b0}}};
    

    reg rw_ready;
    wire rw_ready_nxt = trans_done;
    wire rw_ready_en      = trans_done | rw_ready;
    always @(posedge clock) begin
        if (reset) begin
            rw_ready <= 0;
        end
        else if (rw_ready_en) begin
            rw_ready <= rw_ready_nxt;
        end
    end
    assign rw_ready_o     = rw_ready;
/*
    reg [1:0] rw_resp;
    wire [1:0] rw_resp_nxt = w_trans ? axi_b_resp_i[1:0] : axi_r_resp_i[1:0];
    wire resp_en = trans_done;
    always @(posedge clock) begin
        if (reset) begin
            rw_resp <= 0;
        end
        else if (resp_en) begin
            rw_resp <= rw_resp_nxt;
        end
    end
*/
 // ------------------Number of transmission------------------
    //传输次数
    reg [7:0] len;
    wire len_reset = reset | (w_trans & w_stata_idle) | (r_trans & r_state_idle);
    wire len_incr_en;
    assign len_incr_en = (len != axi_len) & (w_hs | r_hs);
    always @(posedge clock) begin
        if (len_reset) begin
            len <= 0;
        end
        else if (len_incr_en) begin
            len <= len + 1;
        end
    end
    // ------------------Write Transaction------------------
assign axi_aw_valid_o=w_state_addr;
assign axi_aw_addr_o=axi_write_addr;
assign axi_aw_id_o=4'b0011;  
assign axi_aw_len_o= axi_len;
assign axi_aw_size_o= {{1'b0},w_axi_size};//(axi_write_addr<64'h80000000)?3'b010:3'b011;//
assign axi_w_valid_o=w_state_write;
assign axi_aw_burst_o=2'b01;
assign axi_w_strb_o=w_mem_mask;
assign axi_b_ready_o=w_state_resp;
assign axi_w_last_o=1'b1;
always @(posedge clock) begin
    if(reset) begin
        axi_w_data_o<=0;
    end
    else if(aw_hs)
    begin
        axi_w_data_o<=data_write_i;
    end
end

    // ------------------Read Transaction------------------
    //wire clint_skip_ready;
    assign axi_ar_valid_o   = (rw_valid_i)?r_state_addr:0;
    assign axi_ar_addr_o    = axi_addr;
    assign axi_ar_id_o      = axi_id;
    assign axi_ar_len_o     = axi_len;
    assign axi_ar_burst_o   = 2'b01;
    assign axi_ar_size_o    = {{1'b0},rw_size_i};
    assign axi_r_ready_o    = r_state_read;
    //csr CLINT
    assign mtimecmp_data=(axi_aw_addr_o==64'h2004000)?axi_w_data_o:(((axi_addr==64'h2004000)&&(axi_r_id_i==4'b0001&&r_hs==1'b1))?mtimecmp:64'h0);
    assign mtimecmp_open=(((axi_addr==64'h2004000)&&(axi_r_id_i==4'b0001&&r_hs==1'b1))||((axi_aw_addr_o==64'h2004000)&&(axi_write_valid)))?1:0;
    assign mtime_data=(axi_aw_addr_o==64'h200bff8)?axi_w_data_o:(((axi_addr==64'h200bff8)&&(axi_r_id_i==4'b0001&&r_hs==1'b1))?mtime:64'h0);
    assign mtime_open=(((axi_addr==64'h200bff8)&&(axi_r_id_i==4'b0001&&r_hs==1'b1))||((axi_aw_addr_o==64'h200bff8)&&(axi_write_valid)))?1:0;
    //wire [YSYX210448_AXI_DATA_WIDTH-1:0] axi_r_data_l  = (axi_r_data_i & mask_l) >> aligned_offset_l;
    //wire [YSYX210448_AXI_DATA_WIDTH-1:0] axi_r_data_h  = (axi_r_data_i & mask_h) << aligned_offset_h;
/*
    generate
        for (genvar i = 0; i < TRANS_LEN; i=i+1) begin
            always @(posedge clock) begin
                axi_r_hs_o<=r_hs;
                if (reset) begin
                    data_read_o[i*YSYX210448_AXI_DATA_WIDTH+:YSYX210448_AXI_DATA_WIDTH] <= 0;
                end
                else if (axi_r_ready_o & axi_r_valid_i) begin 
                        axi_r_id_o<=axi_r_id_i;                               
                        if (~aligned & overstep) begin
                        if (len[0]) begin
                            data_read_o[YSYX210448_AXI_DATA_WIDTH-1:0] <= data_read_o[YSYX210448_AXI_DATA_WIDTH-1:0] | axi_r_data_h;
                            if(axi_addr==64'h2004000) 
                            mem_data_read<=mtimecmp;
                            else if(axi_addr==64'h200bff8)
                            mem_data_read<=mtime;
                            else
                            mem_data_read<=axi_r_data_i;
                           
                        end
                        else begin
                            data_read_o[YSYX210448_AXI_DATA_WIDTH-1:0] <= axi_r_data_l;
                           if(axi_addr==64'h2004000) 
                            mem_data_read<=mtimecmp;
                            else if(axi_addr==64'h200bff8)
                            mem_data_read<=mtime;
                            else
                            mem_data_read<=axi_r_data_i;
                       
                        end
                        end                      
                        else if (len == i) begin
                        data_read_o[i*YSYX210448_AXI_DATA_WIDTH+:YSYX210448_AXI_DATA_WIDTH] <= axi_r_data_l;
                        if(axi_addr==64'h2004000) 
                            mem_data_read<=mtimecmp;
                            else if(axi_addr==64'h200bff8)
                            mem_data_read<=mtime;
                            else
                            mem_data_read<=axi_r_data_i;                  
                    end
                end
            end
        end
    endgenerate
*/
          always @(posedge clock) begin
                axi_r_hs_o<=r_hs;
                if (reset) begin
                    data_read_o[63:0] <= 64'b0;
                    mem_data_read[63:0] <=64'b0;
                    axi_r_id_o<=4'b0;
                    axi_r_hs_o<=1'b0;
                end
                else if (axi_r_ready_o & axi_r_valid_i) begin 
                        axi_r_id_o<=axi_r_id_i;                               
                        data_read_o[63:0] <= {{32{1'b0}},{axi_r_data_i[31:0]}};
                        if(axi_addr==64'h2004000) 
                          mem_data_read<=mtimecmp;
                        else if(axi_addr==64'h200bff8)
                          mem_data_read<=mtime;
                        else
                          mem_data_read<=axi_r_data_i;                  
                end                
            end

endmodule



module ysyx_210448_cpu(
input clock,
input reset, 
input [3:0] axi_r_id_i,
input axi_read_ready,
input [63:0] axi_data_read,
input [63:0] mtimecmp_data,
input mtimecmp_open,
input [63:0] mtime_data,
input mtime_open,
input r_hs,
input b_hs,
//output mem_read,
output [63:0] mtime,
output [63:0] mtimecmp,
//output [2:0] exe_s1,
input [63:0] r_data,
output  axi_read_valid,
output [63:0] axi_read_addr,
output [1:0] axi_size,
output [1:0] w_axi_size,
output [63:0] axi_write_data,
output [63:0] axi_write_addr,
output [7:0] axi_write_mask,
output [3:0] axi_id,
output axi_mem_write,
output mem_write
);
wire mem_read;
wire [2:0] exe_s1;
wire if_id_bubble;
wire id_exe_bubble;
//if_stage
wire if_ar_hand;
wire pc_write;
wire if_ar_valid;
wire [63 : 0] if_pc;
wire [31 : 0] if_inst;
wire if_stop;
wire if_fetched;
//IF_ID
wire if_id_en;
wire [63 : 0] id_pc;
wire [31 : 0] id_inst;
//id_stage
wire [4 : 0]id_rd;
wire [6:0] id_opcode;
wire [19 : 0]id_u_imm;
wire [19 : 0]id_j_imm;
wire [11 : 0]id_j_imm_j;
wire [11 : 0]id_i_imm;
wire [11 : 0]id_I_imm;
wire [6 : 0]id_b_imm;
wire [6 : 0]id_s_imm;
wire [4 : 0]id_s_imm_s;
wire [4 : 0]id_b_imm_b;
wire [11:0]id_w_imm;
wire [5:0]id_w_shamt;
wire [2:0] id_s1;
wire id_s2;
wire [5:0]id_shamt;
wire [11:0]id_csr;
wire [4:0]id_zimm;
wire id_csr_read;
wire id_csr_write;
wire [63:0] id_op1;
wire [63:0] id_op2;
wire id_ena1;
wire id_ena2;
wire [4:0]id_rs1;
wire [4:0]id_rs2;
//ID_EXE
wire [63:0] id_t;
wire id_exe_en;
wire [63:0] exe_pc;
wire [31:0] exe_inst;
wire [63:0] exe_op1;
wire [63:0] exe_op2;
wire [4 : 0]exe_rd;
wire [6:0] exe_opcode;
wire [19 : 0]exe_u_imm;
wire [19 : 0]exe_j_imm;
wire [11 : 0]exe_j_imm_j;
wire [11 : 0]exe_i_imm;
wire [11 : 0]exe_I_imm;
wire [6 : 0]exe_b_imm;
wire [6 : 0]exe_s_imm;
wire [4 : 0]exe_s_imm_s;
//wire [4 : 0]exe_i_imm_i;
wire [4 : 0]exe_b_imm_b;
wire [11:0]exe_w_imm;
wire [5:0]exe_w_shamt;
wire exe_s2;
wire [5:0]shamt;
wire [11:0]exe_csr;
wire [4:0]exe_zimm;
//wire exe_csr_read;
wire exe_csr_write;
//exe_stage
wire [63:0] p_exe_op1;
wire [63:0] p_exe_op2;
wire p_ready1;
wire p_ready2;
wire exe_pc_write;
wire [63:0]exe_t;
//wire [63:0]exe_csr_data;
//wire [`YSYX210448_REG_BUS] exe_data;
wire exe_w_ena;

//EXE_MEM
wire exe_mem_en;
wire [63:0]mem_pc;
wire [31:0] mem_inst;
wire [6:0]mem_opcode;
wire [6:0]mem_s_imm;
wire [4:0]mem_s_imm_s;
wire [63:0]mem_op1;
wire [63:0]mem_op2;
wire [11:0] mem_I_imm;
wire [2:0] mem_s1;
wire mem_w_ena;
wire [63:0] mem_csr_data;
//wire mem_csr_read;
wire mem_csr_write;
wire [11:0] mem_csr;
wire [63:0] mem_data;
//mem_stage
//wire mem_read;
wire [63:0] mem_read_data;
//MEM_WB
wire [4:0] mem_rd;
wire mem_wb_en;
wire [63:0]wb_pc;
wire [31:0] wb_inst;
wire wb_w_ena;
wire [4:0] wb_rd;
wire [`YSYX210448_REG_BUS] wb_data;
wire wb_read;
wire [63:0]wb_read_data;
wire [11:0]wb_csr;
wire wb_csr_write;
wire [63:0] wb_csr_data;

//wb_stage
//wire ena2;
wire [63:0] pc_add;
//csr
wire exe_mem_bubble;
wire csr_pc_write;
wire [63:0] csr_pc_add;
wire [63:0] exe_pc_add;
//axi
wire id_fetched;
wire exe_fetched;
wire mem_fetched;
wire wb_fetched;
wire [63:0] mem_read_addr;
wire [63:0] rdata;
wire [63:0] if_data_read;
wire [63:0] if_addr;
wire [3:0] if_read_id;
wire [3:0] mem_read_id;
wire axi_mem_read;
//wire wb_write;
wire if_mem_read;
wire id_mem_read;
wire exe_mem_read;
wire mem_mem_read;
//wire ena1;
wire [2:0]s3;
wire wb_write_ready;
wire mem_write_ready;
//wire if_mem_write;
//wire id_mem_write;
wire if_w_ena;
wire id_w_ena;
wire ld;


ysyx_210448_cpu_abtiter ysyx_210448_cpu_abtiter(
.rst(reset),
.if_read_id(if_read_id),
.mem_read_id(mem_read_id),
.pc_write(pc_write),
.pc_add(pc_add),
.exe_pc_write(exe_pc_write),
.exe_pc_add(exe_pc_add),
.csr_pc_write(csr_pc_write),
.csr_pc_add(csr_pc_add),
.axi_id(axi_id),
.if_inst(if_inst),
.wb_read(wb_read),
//.mem_s1(mem_s1),
.w_axi_size(w_axi_size),
.axi_mem_write(mem_write),
.axi_write_addr(axi_write_addr),
.axi_r_id_i(axi_r_id_i),
.axi_mem_read(axi_mem_read),
.mem_read(mem_read),
.if_addr(if_addr),
.if_ar_valid(if_ar_valid),
.r_data(r_data),
.mem_read_addr(mem_read_addr),
//.axi_read_ready(axi_read_ready),
.axi_data_read(axi_data_read),
.if_read_data(if_data_read),
.mem_read_data(rdata),
.axi_read_valid(axi_read_valid),
.axi_addr(axi_read_addr),
.axi_size(axi_size),
.stop(if_stop),
.mem_wb_en(mem_wb_en)
);

ysyx_210448_if_stage ysyx_210448_if_stage(
.clk(clock),
.rst(reset),
.r_hs(r_hs),
.b_hs(b_hs),
.mem_write(mem_write),
.pc_add(pc_add),
.pc_write(pc_write),
.if_ar_hand(if_ar_hand),
.axi_mem_read(axi_mem_read),
.axi_mem_write(axi_mem_write),
.if_read_id(if_read_id),
.if_pc(if_pc),
.if_w_ena(if_w_ena),
.if_inst(if_inst),
.if_id_en(if_id_en),
.stop(if_stop),
.if_ready(axi_read_ready),
.if_mem_read(if_mem_read),
.if_data_read(if_data_read),
.if_valid(if_ar_valid),
.if_addr(if_addr),
.if_fetched(if_fetched)
);
ysyx_210448_IF_ID ysyx_210448_IF_ID(
.clk(clock),
.rst(reset),
.if_pc(if_pc),
.if_inst(if_inst),
.if_w_ena(if_w_ena),
.if_mem_read(if_mem_read),
.id_mem_read(id_mem_read),
.if_fetched(if_fetched),
.id_pc(id_pc),
.id_inst(id_inst),
.id_w_ena(id_w_ena),
.if_id_en(if_id_en),
.if_id_bubble(if_id_bubble),
.id_fetched(id_fetched)
);
ysyx_210448_id_stage ysyx_210448_id_stage(
.id_inst(id_inst),
.id_rd(id_rd),
.id_opcode(id_opcode),
.id_u_imm(id_u_imm),
.id_j_imm(id_j_imm),
.id_j_imm_j(id_j_imm_j),
.id_i_imm(id_i_imm),
.id_I_imm(id_I_imm),
.id_b_imm(id_b_imm),
.id_s_imm(id_s_imm),
.id_s_imm_s(id_s_imm_s),
.id_b_imm_b(id_b_imm_b),
.id_w_imm(id_w_imm),
.id_w_shamt(id_w_shamt),
.id_s1(id_s1),
.id_s2(id_s2),
.id_shamt(id_shamt),
.id_csr(id_csr),
.id_zimm(id_zimm),
.id_csr_read(id_csr_read),
.id_csr_write(id_csr_write),
.id_rs1(id_rs1),
.id_rs2(id_rs2),
.id_ena1(id_ena1),
.id_ena2(id_ena2),
.id_exe_en(id_exe_en)
);
//stop信号，暂停流水线，open信号，开启流水线，如果stop=1,则 发出一个open信号随着流水线传递下去，直到wb阶段，将wb_ok置1,流水线开始

ysyx_210448_pause ysyx_210448_Pause(
  .clk(clock),
  .rst(reset),
  .ld(ld),
  .if_fetched(if_fetched),
  .id_fetched(id_fetched),
  .exe_opcode(exe_opcode),
  .mem_opcode(mem_opcode),
  //.exe_data(exe_data),
  .mem_data(mem_data),
  .wb_data(wb_data),
  .p_exe_op1(p_exe_op1),
  .p_exe_op2(p_exe_op2),
  .p_ready1(p_ready1),
  .p_ready2(p_ready2),
  .id_rs1(id_rs1),
  .id_rs2(id_rs2),
  .exe_rd(exe_rd),
  .mem_rd(mem_rd)
);

ysyx_210448_ID_EXE ysyx_210448_ID_EXE(
.clk(clock),
.rst(reset),
.id_pc(id_pc),
.id_inst(id_inst),
.id_fetched(id_fetched),
.id_mem_read(id_mem_read),
.id_w_ena(id_w_ena),
.id_op1(id_op1),
.id_op2(id_op2),
.id_t(id_t),
.id_rd(id_rd),
.id_opcode(id_opcode),
.id_u_imm(id_u_imm),
.id_j_imm(id_j_imm),
.id_j_imm_j(id_j_imm_j),
.id_i_imm(id_i_imm), 
.id_I_imm(id_I_imm),
.id_b_imm(id_b_imm),
.id_s_imm(id_s_imm),
.id_s_imm_s(id_s_imm_s),
.id_b_imm_b(id_b_imm_b),
.id_w_imm(id_w_imm),
.id_w_shamt(id_w_shamt),
.id_s1(id_s1),
.id_s2(id_s2),
.id_shamt(id_shamt),
.id_csr(id_csr),
.id_zimm(id_zimm),
//.id_csr_read(id_csr_read),
.id_csr_write(id_csr_write),
.exe_pc(exe_pc),
.exe_inst(exe_inst),
.exe_fetched(exe_fetched),
.exe_mem_read(exe_mem_read),
.exe_op1(exe_op1),
.exe_op2(exe_op2),
.exe_t(exe_t),
.exe_rd(exe_rd),
.exe_w_ena(exe_w_ena),
.exe_opcode(exe_opcode),
.exe_u_imm(exe_u_imm),
.exe_j_imm(exe_j_imm),
.exe_j_imm_j(exe_j_imm_j),
.exe_i_imm(exe_i_imm), 
.exe_I_imm(exe_I_imm),
.exe_b_imm(exe_b_imm),
.exe_s_imm(exe_s_imm),
.exe_s_imm_s(exe_s_imm_s),
//.exe_i_imm_i(exe_i_imm_i),
.exe_b_imm_b(exe_b_imm_b),
.exe_w_imm(exe_w_imm),
.exe_w_shamt(exe_w_shamt),
.exe_s1(exe_s1),
.exe_s2(exe_s2),
.exe_shamt(shamt),
.exe_csr(exe_csr),
.exe_zimm(exe_zimm),
//.exe_csr_read(exe_csr_read),
.exe_csr_write(exe_csr_write),
.id_exe_en(id_exe_en),
.id_exe_bubble(id_exe_bubble)
);
ysyx_210448_exe_stage ysyx_210448_exe_stage(
.clk(clock),
.rst(reset),
.s3(s3),
.exe_fetched(exe_fetched),
.exe_op1(exe_op1),
.exe_op2(exe_op2),
.exe_pc(exe_pc),
.p_exe_op1(p_exe_op1),
.p_exe_op2(p_exe_op2),
.p_ready1(p_ready1),
.p_ready2(p_ready2),
.exe_opcode(exe_opcode),
.exe_mem_read(exe_mem_read),
.mem_mem_read(mem_mem_read),
.r_hs(r_hs),
.axi_r_id_i(axi_r_id_i),
.mem_read(mem_read),
.exe_u_imm(exe_u_imm),
.exe_j_imm(exe_j_imm),
.exe_j_imm_j(exe_j_imm_j),
.exe_i_imm(exe_i_imm),
.exe_b_imm(exe_b_imm),
.exe_I_imm(exe_I_imm),
.exe_w_imm(exe_w_imm),
.exe_w_shamt(exe_w_shamt),
.shamt(shamt),
.exe_b_imm_b(exe_b_imm_b),
.exe_s1(exe_s1),
.exe_s2(exe_s2),
.exe_t(exe_t),
.exe_zimm(exe_zimm),
.exe_csr_data_re(mem_csr_data),
.exe_data_re(mem_data),
.exe_pc_add_re(exe_pc_add),
.exe_pc_write(exe_pc_write),
.exe_mem_en(exe_mem_en),
.if_id_bubble(if_id_bubble),
.id_exe_bubble(id_exe_bubble),
.exe_mem_bubble(exe_mem_bubble)
);
ysyx_210448_EXE_MEM ysyx_210448_EXE_MEM(
.clk(clock),
.rst(reset),
.exe_pc(exe_pc),
.exe_mem_bubble(exe_mem_bubble),
.exe_inst(exe_inst),
.exe_fetched(exe_fetched),
.exe_mem_read(exe_mem_read),
.exe_rd(exe_rd),
.exe_opcode(exe_opcode),
.exe_s_imm(exe_s_imm),
.exe_s_imm_s(exe_s_imm_s),
.exe_op1(exe_op1),
.exe_op2(exe_op2),
.exe_I_imm(exe_I_imm),
.exe_s1(exe_s1),
//.exe_data(exe_data),
.exe_w_ena(exe_w_ena),
.exe_csr(exe_csr),
//.exe_csr_data(exe_csr_data),
//.exe_csr_read(exe_csr_read),
.exe_csr_write(exe_csr_write),
.mem_fetched(mem_fetched),
.mem_pc(mem_pc),
.mem_inst(mem_inst),
.mem_mem_read(mem_mem_read),
.mem_rd(mem_rd),
.mem_opcode(mem_opcode),
.mem_s_imm(mem_s_imm),
.mem_s_imm_s(mem_s_imm_s),
.mem_op1(mem_op1),
.mem_op2(mem_op2),
.mem_I_imm(mem_I_imm),
.mem_s1(mem_s1),
//.mem_data(mem_data),
.mem_w_ena(mem_w_ena),
.mem_csr(mem_csr),
//.mem_csr_data(mem_csr_data),
//.mem_csr_read(mem_csr_read),
.mem_csr_write(mem_csr_write),
.exe_mem_en(exe_mem_en)
);
ysyx_210448_mem_stage ysyx_210448_mem_stage(
.clk(clock),
.rst(reset),
.b_hs(b_hs),
.mem_fetched(mem_fetched),
.s3(s3),
.mem_opcode(mem_opcode),
.mem_write_ready(mem_write_ready),
.mem_read_id(mem_read_id),
.mem_s_imm(mem_s_imm),
.mem_s_imm_s(mem_s_imm_s),
.mem_op1(mem_op1),
.mem_op2(mem_op2),
.mem_I_imm(mem_I_imm),
.mem_s1(mem_s1),
//.axi_size(axi_size),
.mem_read_addr(mem_read_addr),
.rdata(rdata),
.mem_read_data(mem_read_data),
.mem_write_addr(axi_write_addr),
.wmask(axi_write_mask),
.wdata(axi_write_data),
.axi_mem_write(axi_mem_write),
//.mem_wb_en(mem_wb_en),
.mem_write(mem_write),
.wb_write_ready(wb_write_ready)
);
ysyx_210448_MEM_WB ysyx_210448_MEM_WB(
.clk(clock),
.rst(reset),
.mem_write_ready(mem_write_ready),
//.mem_write(mem_write),
.mem_wb_en(mem_wb_en),
.mem_pc(mem_pc),
.mem_inst(mem_inst),
.mem_fetched(mem_fetched),
.mem_w_ena(mem_w_ena),
.mem_rd(mem_rd),
.mem_data(mem_data),
.mem_read(mem_read),
.mem_read_data(mem_read_data),
.mem_csr(mem_csr),
.mem_csr_write(mem_csr_write),
//.mem_csr_read(mem_csr_read),
.mem_csr_data(mem_csr_data),
.wb_write_ready(wb_write_ready),
.wb_fetched(wb_fetched),
//.wb_write(wb_write),
.wb_pc(wb_pc),
.wb_inst(wb_inst),
.wb_w_ena(wb_w_ena),
.wb_rd(wb_rd),
.wb_data(wb_data),
.wb_read(wb_read),
.wb_read_data(wb_read_data),
.wb_csr(wb_csr),
.wb_csr_write(wb_csr_write),
.wb_csr_data(wb_csr_data)
);
ysyx_210448_wb_stage ysyx_210448_wb_stage(
.clk(clock),
.rst(reset),
.ld(ld),
.wb_inst(wb_inst),
.if_pc(if_pc),
.mtime(mtime),
.mem_fetched(mem_fetched),
.mtimecmp(mtimecmp),
.exe_pc_write(exe_pc_write),
//.exe_fetched(exe_fetched),
.exe_pc_add(exe_pc_add),
.if_fetched(if_fetched),
.if_ar_hand(if_ar_hand),
.mtimecmp_data(mtimecmp_data),
.mtimecmp_open(mtimecmp_open),
.mtime_data(mtime_data),
.mtime_open(mtime_open),
.wb_fetched(wb_fetched),
.exe_w_ena(exe_w_ena),
.id_ena1(id_ena1),
.id_ena2(id_ena2),
.id_rs1(id_rs1),
.id_rs2(id_rs2),
.id_op1(id_op1),
.id_op2(id_op2),
.wb_pc(wb_pc),
.if_w_ena(if_w_ena),
.wb_w_ena(wb_w_ena),
.wb_rd(wb_rd),
.wb_data(wb_data),
.wb_read(wb_read),
.axi_mem_read(axi_mem_read),
.axi_mem_write(axi_mem_write),
.wb_read_data(wb_read_data),
.id_csr(id_csr),
.wb_csr(wb_csr),
.wb_csr_write(wb_csr_write),
.id_csr_read(id_csr_read),
.wb_csr_data(wb_csr_data),
.id_t(id_t),
.csr_pc_add(csr_pc_add),
.csr_pc_write(csr_pc_write)//,
//.ena1(ena1),
//.ena2(ena2)
);

endmodule


module ysyx_210448_clint (
  input wire clk,
  input rst,
  input wire [63:0] mtimecmp_data,
  input wire mtimecmp_open,
  input wire [63:0] mtime_data,
  input wire mtime_open,
  input wire [63:0] mstatus,
  input wire [63:0] mie,
  output reg [63:0] mcause_data,
  output reg [63:0] mtime,
  output reg [63:0] mtimecmp,
  output reg clock_interrupt
);
//reg [63:0] mtimecmp;
//reg [63:0] mtime;
always @(posedge clk) 
	begin
		if (rst==1'b1) 
		begin
			mtime<=`YSYX210448_ZERO_WORD;
			mtimecmp<=`YSYX210448_ZERO_WORD;
		end
		else 
		begin
      mtime<=mtime+1;
			if (mtimecmp_open)
			begin
				mtimecmp<=mtimecmp_data;
			end
      if(mtime_open)
      begin
        mtime<=mtime_data;
      end
      else
      begin
        mtime<=mtime+1;
      end
		end
	end
always @(*) begin
  if(rst)
  begin
     mcause_data=`YSYX210448_ZERO_WORD;
     clock_interrupt=1'b0;
  end
  else
  begin
     if((mtime>=mtimecmp)&&(mie[7]==1'b1)&&(mstatus[3]==1'b1))//时钟中断
     begin
      mcause_data=64'h8000000000000007;
      clock_interrupt=1'b1;
     end
     else
     begin
      clock_interrupt=1'b0;
      mcause_data=64'hb;
     end
  end
 end  


endmodule
/*备注（防止遗忘）
由于mem所取得数据不需要处理（在mem阶段有处理），所以直接将总线取得数据r_data传递给mem_read_data(同时用配套的axi_r_id判断数据来源)
if所取的值是经过axi_rw模块内部处理后才得到的axi_read_data(同时用配套的axi_r_id_o判断数据来源)
综上if得到的值要比mem晚一个周期
原因：本来是懒的改axi_rw,又加上mem阶段有处理，没想到多处理了一天（信号作用时间一直不对）
教训：有时候为了省功夫可能还会花上更多时间（气泡法改数据前递同理）
*/
/*上面的出问题了，所以我又改回来了
备注（11.12）
改完后，只有一个信号是提前的（axi_r_id），新处理如下：mem阶段取数据后，直接将暂存的if_addr发出，等到下一条指令回来时，拉高mem_wb_en，提前信号的意义，让wb阶段和对
axi_data的处理同时进行
问题：仲裁做好的处理，并没有和总线那边联系起来，这里axi_read_valid为低是，总线为高
教训：有问题就问
*/
/*
修改:mem_wb_en先拉高，在拉低stop(11.14)
*/
//id=1取数据，id=2取指令,id=3写数据



module ysyx_210448_cpu_abtiter(
  input wire rst,
  input wire exe_pc_write,
  input wire [63:0] exe_pc_add,
  input wire csr_pc_write,
  input wire axi_mem_write,
  input wire [63:0] axi_write_addr,
  input wire [63:0] csr_pc_add,
  input wire [31:0] if_inst,
  input wire axi_mem_read,
  input wire mem_read,
  input wire if_ar_valid,
  input wire [3:0]if_read_id,
  input wire [3:0]mem_read_id,
  input wire [3:0]axi_r_id_i,
  input wire wb_read,
  input wire [63:0] r_data,
  input wire [63:0] if_addr,
  //input wire [2:0] mem_s1,
  input wire [63:0] mem_read_addr,
  //input wire axi_read_ready,
  input  wire [63:0] axi_data_read,
  output wire [63:0] if_read_data,
  output wire [63:0] mem_read_data,
  output  wire axi_read_valid,
  output reg [63:0] axi_addr,
  output reg [1:0] axi_size,
  output reg [1:0] w_axi_size,
  output reg [3:0] axi_id,
  output wire stop,
  output reg pc_write,
  output reg [63:0] pc_add,
  output wire mem_wb_en
);
wire mem_read_close;
assign axi_read_valid=((if_inst==32'b0)&&(exe_pc_write==1'b1))?0:((axi_mem_read)?mem_read:if_ar_valid);
/*assign axi_read_valid=(((if_inst==32'b0)&&(exe_pc_write==1'b1))
                      ||(axi_addr==64'h2004000)
                      ||(axi_addr==64'h200bff8))?
                      0:((axi_mem_read)?mem_read:if_ar_valid);
                      */
assign stop=(mem_read)?((wb_read&&axi_r_id_i==4'b0010)?1'b0:1'b1):(1'b0);//wb_read
assign mem_wb_en=(mem_read)?((axi_r_id_i==4'b0001)?1'b1:1'b0):1'b1;//axi_r_id==4'b0010&&r_hs
assign mem_read_close=(axi_r_id_i==4'b0001)?1:0;//
assign if_read_data=(axi_r_id_i==4'b0010)?axi_data_read:0;
assign mem_read_data=(axi_r_id_i==4'b0001)?r_data:0;


always @(*) begin
  if (rst) begin
    axi_addr=64'b0;
    axi_id=4'b0;
    axi_size=`YSYX210448_SIZE_W;
    w_axi_size=2'b0;
    pc_write=1'b0;
    pc_add=64'b0;
  end
  else begin
  if(axi_mem_read&&~mem_read_close)
  begin
      axi_addr=mem_read_addr;//{mem_read_addr[63:3],{3{1'b0}}};
      axi_id=mem_read_id;
      //axi_size=mem_s1[1:0];
  end
  else
  begin    
      axi_addr=if_addr;
      axi_id=if_read_id;
      //axi_size = `YSYX210448_SIZE_W;
  end
  if(axi_mem_read&&~mem_read_close) begin
  axi_size=((axi_addr==64'h2004000)||(axi_addr==64'h200bff8))?2'b10:if_inst[13:12];
  w_axi_size=2'b0;
  end
  else if(axi_mem_write) begin
  axi_size = `YSYX210448_SIZE_W;
  w_axi_size=((axi_write_addr==64'h2004000)||(axi_write_addr==64'h200bff8))?2'b10:if_inst[13:12];
  end
  else begin
  axi_size = `YSYX210448_SIZE_W;
  w_axi_size=2'b0;
  end
  //end
  if(csr_pc_write)
  begin
    pc_write=csr_pc_write;
    pc_add=csr_pc_add;
  end
  else
  begin
    pc_write=exe_pc_write;
    pc_add=exe_pc_add;
  end
  end
end


//assign axi_size = `YSYX210448_SIZE_W;

endmodule


module ysyx_210448_CSR(
    input wire clk,
	input wire rst,
    input wire if_fetched,
    input wire wb_fetched,
    //input wire exe_fetched,
    input wire mem_fetched,
    input wire exe_pc_write,
    input wire if_ar_hand,
    input wire wb_read,
    input wire [63:0] if_pc,
    input wire [63:0] exe_pc_add,
    input wire [31:0] wb_inst,
	  input wire [11:0] id_csr,
    input wire [11:0] wb_csr,
    input wire wb_csr_write,
	  input wire id_csr_read,
    input wire [4:0] id_rs1,
    input wire [4:0] wb_rd,
    input wire [63:0] mtimecmp_data,
    input wire mtimecmp_open,
    input wire [63:0] mtime_data,
    input wire mtime_open,
    input wire [63:0] csr_data,
    input wire [63:0]pc,
    output wire [63:0] mtime,
    output wire [63:0] mtimecmp,
    output reg [63:0]id_t,
    output reg [63:0] csr_pc_add,
    output reg csr_pc_write
    );
reg [63:0] mstatus;
reg [63:0] sstatus;
reg [63:0] mepc;
reg [63:0] mtvec;
reg [63:0] mcause;
reg [63:0] mip;
reg [63:0] mie;
reg [63:0] mcycle;
reg [63:0] mscratch;
wire [63:0] mcause_data;
reg [63:0] rmstatus;
reg [63:0] mhartid;
wire clock_interrupt;

//wire clock_interrupt;

//包含mtime,mtimecmp
ysyx_210448_clint ysyx_210448_clint(
.clk(clk),
.rst(rst),
.mtime(mtime),
.mtimecmp(mtimecmp),
.mtimecmp_data(mtimecmp_data),
.mtimecmp_open(mtimecmp_open),
.mtime_data(mtime_data),
.mtime_open(mtime_open),
.mcause_data(mcause_data),
.mie(mie),
.mstatus(mstatus),
.clock_interrupt(clock_interrupt)
);

reg interrupt_ready1;
wire interrupt;

reg wb_stage;
reg [63:0] mepc_exe;
always @(posedge clk) begin
  if(rst)
  begin
    mepc_exe<=0;
    wb_stage<=0;
    interrupt_ready1<=0;
  end
  else
  begin
    if((mem_fetched)&&(exe_pc_write))
    mepc_exe<=exe_pc_add;
    else if(if_fetched)
    mepc_exe<=if_pc+4;
    if((wb_fetched)||(wb_read))
    wb_stage<=1'b1;
    else if(if_ar_hand)
    wb_stage<=1'b0;
    if(clock_interrupt)
    interrupt_ready1<=1'b1;
    else if(if_fetched)
    interrupt_ready1<=1'b0;
  end
end

assign interrupt=(wb_stage)?((clock_interrupt)?clock_interrupt:interrupt_ready1):0;


always @(posedge clk) begin
  if(rst)
  begin
    csr_pc_write<=0;
    csr_pc_add<=0;
  end
  else
  begin
    if(interrupt)
    begin
    csr_pc_write<=1'b1;
    csr_pc_add<={mtvec[63:2],2'b0};
    end
    else if((wb_csr_write)&&wb_csr==12'h302)
    begin
    csr_pc_write<=1'b1;
    csr_pc_add<=mepc;
    end
    else if((wb_csr_write)&&wb_csr==12'h000)
    begin
    csr_pc_write<=1'b1;
    csr_pc_add<={mtvec[63:2],2'b0};
    end
    else if(if_fetched)
    begin
    csr_pc_write<=1'b0;
    csr_pc_add<=64'b0;
    end
  end
end

reg mstatus_mie;
reg mstatus_mpie;
wire [1:0] mpp=2'b11;
reg [1:0] mstatus_fs;
always @(posedge clk) 
begin
  mcycle<=mcycle+1;//mcycle赋值
  if (rst==1'b1) 
  begin
	  mstatus<=`YSYX210448_ZERO_WORD;
    mepc<=`YSYX210448_ZERO_WORD;
    mtvec<=`YSYX210448_ZERO_WORD;
    mcause<=`YSYX210448_ZERO_WORD;
    sstatus<=64'b0;
    mcycle<=`YSYX210448_ZERO_WORD;
    mie<=`YSYX210448_ZERO_WORD;
    mscratch<=`YSYX210448_ZERO_WORD;
    mip<=`YSYX210448_ZERO_WORD;
    mhartid<=`YSYX210448_ZERO_WORD;
    mstatus_mpie<=1'b0;
    mstatus_mie<=1'b0;
    mstatus_fs<=2'b0;
    mcycle<=64'b0;
    rmstatus<=64'b0;
  end
  else
  begin
  if(wb_fetched&&wb_csr_write)
  begin
    case(wb_csr)
    12'h000:
    begin 
    mepc<=pc;
    mcause<=mcause_data;
    mstatus_mpie<=mstatus_mie;
    mstatus<={{mstatus[63:13]},{mpp[1:0]},{mstatus[10:8]},{mstatus_mie},{mstatus[6:4]},{1'b0},{mstatus[2:0]}};
    mstatus_fs<=mstatus[14:13];
    //pc_write=1'b1;
    //pc_add={mtvec[63:2],2'b0};
    end
    12'h305:mtvec<={csr_data[63:2],2'b0};
    12'h300:
    begin 
    if(id_rs1!=5'b0) begin 
    mstatus<={{csr_data[13]},{csr_data[62:0]}}; 
    sstatus<={{csr_data[13]},{csr_data[62:15]},{csr_data[14:13]},{13{1'b0}}};   
    if(((id_rs1!=5'b0)&&(wb_rd!=5'b0))||((mstatus[13])&&(wb_rd==5'b0))) begin
    rmstatus<=csr_data;
    mstatus_mie<=csr_data[3]; 
    mstatus_fs<=csr_data[14:13];
    mstatus_mpie<=csr_data[7]; 
    end  
    end 
    end
    12'h341:if(id_rs1!=5'b0)mepc<=csr_data;
    12'h344:mip<=csr_data;
    12'h304:mie<=csr_data;
    12'h342:mcause<=csr_data;
    12'h340:mscratch<=csr_data;
    12'h302:
    begin 
    mstatus<=(interrupt)?
    rmstatus:
    ({{mstatus_fs[0]},{rmstatus[62:15]},{mstatus_fs},{2{1'b0}},{rmstatus[10:8]},{1'b1},{rmstatus[6:4]},{mstatus_mpie},rmstatus[2:0]});
    end
    12'hf14:mhartid<=csr_data;
    default:;
    endcase
  end
  if(clock_interrupt)
  begin
    if(wb_inst!=32'b0)
    begin
    //mstatus_mie<=mstatus[3]; 
    rmstatus<=mstatus; 
    mstatus_fs<=mstatus[14:13];
    mstatus_mpie<=mstatus[3];
    mepc<=(wb_csr==12'h302)?mepc:mepc_exe;
    mstatus_mpie<=mstatus[3];
    mcause<=mcause_data;
    mip<={{mip[63:8]},{1'b1},{mip[6:0]}};
    mstatus<=(wb_csr==12'h302)?rmstatus:((wb_csr==12'h300)?
    {{csr_data[63:13]},{mpp[1:0]},{csr_data[10:8]},{csr_data[3]},{csr_data[6:4]},{1'b0},{csr_data[2:0]}}
    :{{mstatus[63:13]},{mpp[1:0]},{mstatus[10:8]},{mstatus[3]},{mstatus[6:4]},{1'b0},{mstatus[2:0]}});
    end
  end
   end
end

always @(*) begin
  if (rst == 1'b1) begin
	  id_t=`YSYX210448_ZERO_WORD;
  end
	else if(id_csr_read==1'b1) 
    begin
    case(id_csr)
      12'h000:id_t=mepc;
	    12'h300:id_t=mstatus;  
      12'h341:id_t=mepc; 
      12'h305:id_t=mtvec;
      12'h342:id_t=mcause;
      12'h344:id_t=mip;
      12'h304:id_t=mie;
      12'hf14:id_t=mhartid;
      12'h340:id_t=mscratch;
      12'hb00:begin 
          id_t=mcycle;
          end
	default:id_t=`YSYX210448_ZERO_WORD;
	endcase
    end
	else 
    begin
	  id_t=`YSYX210448_ZERO_WORD; 
    end
end	


	
endmodule



module ysyx_210448_EXE_MEM (
  input clk,
  input wire rst,
  input wire exe_mem_bubble,
  input wire exe_fetched,
  input wire exe_mem_read,
  input wire [63:0]exe_pc,
  input wire [31:0] exe_inst,
  input wire [6:0]exe_opcode,
  input wire [6 : 0]exe_s_imm,
  input wire [4 : 0]exe_s_imm_s,
  input wire [63:0]exe_op1,
  input wire [63:0]exe_op2,
  input wire [11:0] exe_I_imm,
  input wire [2:0] exe_s1,
  input wire [4:0] exe_rd,
  input wire exe_w_ena,
  //input wire [63:0] exe_csr_data,
  //input wire exe_csr_read,
  input wire exe_csr_write,
  input wire [11:0] exe_csr,
  //input wire [63:0] exe_data,
  input wire exe_mem_en,

  output reg [63:0]mem_pc,
  output reg [31:0] mem_inst,
  output reg mem_fetched,
  output reg [6:0]mem_opcode,
  output reg [6:0]mem_s_imm,
  output reg [4:0]mem_s_imm_s,
  output reg [63:0]mem_op1,
  output reg [63:0]mem_op2,
  output reg [11:0] mem_I_imm,
  output reg [4:0] mem_rd,
  output reg mem_w_ena,
  //output reg [63:0] mem_csr_data,
  //output reg mem_csr_read,
  output reg mem_csr_write,
  output reg mem_mem_read,
  output reg [11:0] mem_csr,
  //output reg [63:0] mem_data,
  output reg [2:0] mem_s1
);
    always @(posedge clk) begin
        if(rst==1'b1)
        begin
        mem_pc<=64'b0;
        mem_inst<=32'b0;
        mem_opcode<=7'b0;
        mem_s_imm<=7'b0;
        mem_s_imm_s<=5'b0;
        mem_op1<=64'b0;
        mem_op2<=64'b0;
        mem_I_imm<=12'b0;
        mem_s1<=3'b0;
        mem_rd<=5'b0;
        mem_w_ena<=1'b0;
        //mem_csr_data<=64'b0;
        //mem_csr_read<=1'b0;
        mem_csr_write<=1'b0;
        mem_csr<=12'b0;
        //mem_data<=64'd0;
        mem_fetched<=1'b0;
        mem_mem_read<=1'b0;
        end
        else if(exe_mem_en)
        begin
          if(exe_mem_bubble)
          begin
          mem_pc<=64'b0;
          mem_inst<=32'b0;
          mem_opcode<=7'b0;
          mem_s_imm<=7'b0;
          mem_s_imm_s<=5'b0;
          mem_op1<=64'b0;
          mem_op2<=64'b0;
          mem_I_imm<=12'b0;
          mem_s1<=3'b0;
          mem_rd<=5'b0;
          mem_w_ena<=1'b0;
          //mem_csr_data<=64'b0;
          //mem_csr_read<=1'b0;
          mem_csr_write<=1'b0;
          mem_csr<=12'b0;
          //mem_data<=64'd0;
          mem_fetched<=1'b0;
          mem_mem_read<=1'b0;
          end
          mem_pc<=exe_pc;
          mem_inst<=exe_inst;
          mem_opcode<=exe_opcode;
          mem_s_imm<=exe_s_imm;
          mem_s_imm_s<=exe_s_imm_s;
          mem_op1<=exe_op1;
          mem_op2<=exe_op2;
          mem_I_imm<=exe_I_imm;
          mem_s1<=exe_s1;
          mem_rd<=exe_rd;
          mem_w_ena<=exe_w_ena;
          //mem_csr_data<=exe_csr_data;
          //mem_csr_read<=exe_csr_read;
          mem_csr_write<=exe_csr_write;
          mem_csr<=exe_csr;
          //mem_data<=exe_data;
          mem_fetched<=exe_fetched;
          mem_mem_read<=exe_mem_read;
        end
    end
endmodule


module ysyx_210448_exe_stage(
  input clk,
  input wire rst,
  input wire exe_mem_read,
  input wire mem_mem_read,
  input wire r_hs,
  input wire [63:0] p_exe_op1,
  input wire [63:0] p_exe_op2,
  input wire p_ready1,
  input wire p_ready2,
  input wire [3:0]axi_r_id_i,
  input wire exe_fetched,
  input wire [63:0]exe_op1,
  input wire [63:0]exe_op2,
  input wire [63:0]exe_pc,
  input wire [6:0] exe_opcode,
  input wire [19 : 0]exe_u_imm,
  input wire [19 : 0]exe_j_imm,
  input wire [11 : 0]exe_j_imm_j,
  input wire [11 : 0]exe_i_imm,
  input wire [6 : 0]exe_b_imm,
  input wire [11 : 0]exe_I_imm,
  input wire [11:0]exe_w_imm,
  input wire [5:0]exe_w_shamt,
  input wire [5:0]shamt,
  input wire [4:0] exe_b_imm_b,
  input wire [2:0] exe_s1,
  input wire exe_s2,
  input wire [63:0]exe_t,
  input wire [4:0]exe_zimm,
  output reg [63:0]exe_csr_data_re,
  output reg [`YSYX210448_REG_BUS] exe_data_re,
  output reg exe_pc_write,
  output reg [63:0] exe_pc_add_re,
  output wire exe_mem_en,
  output wire exe_mem_bubble,
  output wire if_id_bubble,
  output wire id_exe_bubble,
  output reg mem_read,
  output reg [2:0] s3
);
//处理后的立即数
assign exe_mem_en=1'b1;
wire [63:0] exe_u_imm_u;
wire [63:0] exe_b_imm_b_b_b;
wire [11:0] exe_b_imm_b_b;
wire [19:0] jal_imm;
//wire [11:0]s_s;
wire imm1;
wire [7:0] imm2;
wire imm3;
wire [9:0] imm4;
wire [5:0]imm5;
wire [3:0]imm6;
wire [5:0]sra_imm;
wire [4:0]sra_imm_w;
wire [4:0]sll_imm;
wire [5:0]sll_imm_sll;
wire [5:0]srl_imm;
wire [4:0]srl_imm_w;
wire [63:0]sllw;
wire [31:0]srlw;
wire [31:0]sraw;
wire [63:0]csr_zimm;

wire [63:0] e_op1;
wire [63:0] e_op2;
assign e_op1=(p_ready1)?p_exe_op1:exe_op1;
assign e_op2=(p_ready2)?p_exe_op2:exe_op2;
assign sll_imm_sll=e_op2[5:0];
assign srl_imm=e_op2[5:0];
assign sra_imm=e_op2[5:0];
assign csr_zimm={{59{1'b0}},exe_zimm[4:0]};
assign imm2=exe_j_imm[7:0];
assign imm5=exe_b_imm[5:0];
assign imm4=exe_j_imm[18:9];
assign imm6=exe_b_imm_b[4:1];
assign sll_imm=e_op2[4:0];
assign sllw=e_op1<<sll_imm;
assign srl_imm_w=e_op2[4:0];
assign sra_imm_w=e_op2[4:0];
assign exe_b_imm_b_b={imm1,imm3,imm5,imm6};
assign exe_b_imm_b_b_b=({{52{exe_b_imm_b_b[11]}},exe_b_imm_b_b})<<1;
assign exe_u_imm_u=({{44{exe_u_imm[19]}},exe_u_imm})<<12;
assign jal_imm=({imm3,imm2,imm1,imm4})<<1;
assign imm3=(exe_opcode==7'b1101111)?exe_j_imm[19]:exe_b_imm_b[0];
assign imm1=(exe_opcode==7'b1101111)?exe_j_imm[8]:exe_b_imm[6];
assign srlw=(exe_opcode==7'b0111011)?e_op1[31:0]>>srl_imm_w:
                                     e_op1[31:0]>>exe_w_shamt;
assign sraw=(exe_opcode==7'b0111011)?($signed(e_op1[31:0]))>>>sra_imm_w:
                                      ($signed(e_op1[31:0]))>>>exe_w_shamt;

wire [63:0] exe_data_w_add=e_op1+{{52{exe_w_imm[11]}},exe_w_imm};
wire [63:0] exe_data_w_slli=e_op1<<exe_w_shamt;
wire [63:0] exe_data_addw=e_op1+e_op2;
wire [63:0] exe_data_w_sub=e_op1-e_op2;
assign if_id_bubble=1'b0;
assign id_exe_bubble=1'b0;
assign exe_mem_bubble=(exe_opcode==7'b0001111)?1'b1:1'b0;
//assign exe_pc_add=((exe_opcode==7'b1100011)||(exe_opcode==7'b1101111)||(exe_opcode==7'b1100111))?pc_add:64'b0;
//assign exe_pc_write=((exe_opcode==7'b1100011)||(exe_opcode==7'b1101111)||(exe_opcode==7'b1100111))?pc_write:0;



reg [63:0] exe_pc_add;
reg [63:0] exe_csr_data;
reg [63:0] exe_data;

always @(posedge clk) begin
  if(rst) begin
  exe_csr_data_re<=64'b0;
  exe_data_re<=64'b0;
  exe_pc_add_re<=64'b0;
  end
  else if(exe_fetched)
  begin
    exe_csr_data_re<=exe_csr_data;
    exe_data_re<=exe_data;
    exe_pc_add_re<=exe_pc_add;
    if(exe_pc_add_re[0]==1'b1)
    begin
      exe_pc_add_re[0]<=1'b0;
    end
  end
end



always@(*)
begin
  if(rst)
  begin
  exe_csr_data =`YSYX210448_ZERO_WORD;
  exe_data=`YSYX210448_ZERO_WORD;
  //exe_data_w=`YSYX210448_ZERO_WORD;
  exe_pc_write=1'b0;
  exe_pc_add=`YSYX210448_ZERO_WORD;
  //exe_mem_en=1'b1;
  //if_id_bubble=1'b0;
  //id_exe_bubble=1'b0;
  //exe_mem_bubble=1'b0;
  //exe_u_imm_u=64'b0;
  //exe_b_imm_b_b_b=64'b0;
  //exe_b_imm_b_b=12'b0;
  //jal_imm=20'b0;
  //imm1=1'b0;
  //imm2=8'b0;
  //imm3=1'b0;
  //imm4=10'b0;
  //imm5=6'b0;
  //imm6=4'b0;
  //sra_imm=6'b0;
  //sra_imm_w=5'b0;
  //sll_imm=5'b0;
  //sll_imm_sll=6'b0;
  //srl_imm=6'b0;
  //srl_imm_w=5'b0;
  //sllw=64'b0;
  //srlw=32'b0;
  //sraw=32'b0;
  //csr_zimm=64'b0;
  end
  else begin
  exe_pc_write=1'b0;
  exe_pc_add=64'b0;
  exe_csr_data=64'b0;
  exe_data=64'b0;
  //exe_mem_bubble=1'b0;
  if(exe_opcode==7'b0110011) begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    exe_data=64'b0;
      if(exe_s2==0) begin
      if(exe_s1==3'b000)  exe_data=e_op1+e_op2; //add 
      else if(exe_s1==3'b001) begin  exe_data=e_op1<<sll_imm_sll;end //sll
      else if(exe_s1==3'b010) exe_data=($signed(e_op2)>$signed(e_op1))?1:0;////slt
      else if(exe_s1==3'b011) exe_data=($unsigned(e_op2)>$unsigned(e_op1))?1:0;//sltu
      else if(exe_s1==3'b100) exe_data=e_op1^e_op2;//xor
      else if(exe_s1==3'b101) begin exe_data=e_op1>>srl_imm; end//exe_op1右移exe_op2，空位填0,srl
      else if(exe_s1==3'b110) exe_data=e_op1|e_op2;//or
      else if(exe_s1==3'b111) exe_data=e_op1&e_op2;//and
      else exe_data=64'b0;
      /*
      case(exe_s1)
      3'b000:exe_data=e_op1+e_op2;//add
      3'b001:
      begin
          sll_imm_sll=e_op2[5:0];
          exe_data=e_op1<<sll_imm_sll;//sll
      end
      3'b010:exe_data=($signed(e_op2)>$signed(e_op1))?1:0;//slt
      3'b011:exe_data=($unsigned(e_op2)>$unsigned(e_op1))?1:0;//sltu
      3'b100:exe_data=e_op1^e_op2;//xor
      3'b101:
      begin
        srl_imm=e_op2[5:0];//exe_op1右移exe_op2，空位填0,srl
        exe_data=e_op1>>srl_imm;
      end
      3'b110:exe_data=e_op1|e_op2;//or
      3'b111:exe_data=e_op1&e_op2;//and
      default:exe_data=64'b0;
      endcase
      */
    end
    else begin
      if(exe_s1==3'b00) exe_data=e_op1-e_op2;//sub
      else if(exe_s1==3'b101) begin exe_data=($signed(e_op1))>>>sra_imm;end//exe_op1右移exe_op2,空位用exe_op1最高位填充,sra
      else exe_data=64'b0;
      /*
      case(exe_s1)
      3'b000:exe_data=e_op1-e_op2;//sub
      3'b101:
      begin
        sra_imm=e_op2[5:0];
        exe_data=($signed(e_op1))>>>sra_imm;//exe_op1右移exe_op2,空位用exe_op1最高位填充,sra
      end
      default:exe_data=64'b0;
      endcase
      */
    end
  end
  else if(exe_opcode==7'b0010011)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    exe_data=64'b0;
    if(exe_s1==3'b000) begin exe_data=e_op1+{{52{exe_i_imm[11]}},exe_i_imm};end//addi
    else if(exe_s1==3'b010) exe_data=($signed(e_op1)<$signed({{52{exe_i_imm[11]}},exe_i_imm}))?1:0;//slit 
    else if(exe_s1==3'b011) exe_data=($unsigned(e_op1)<$unsigned({{52{exe_i_imm[11]}},exe_i_imm}))?1:0;//slitu
    else if(exe_s1==3'b100) exe_data=e_op1^{{52{exe_i_imm[11]}},exe_i_imm};//xori
    else if(exe_s1==3'b110) exe_data=e_op1|{{52{exe_i_imm[11]}},exe_i_imm};//ori
    else if(exe_s1==3'b111) exe_data=e_op1&{{52{exe_i_imm[11]}},exe_i_imm};//andi
    else if(exe_s1==3'b001) exe_data=e_op1<<shamt;//slli
    else if(exe_s1==3'b101) begin  if(exe_s2==0) begin exe_data=e_op1>>shamt; end
    else begin exe_data=($signed(e_op1))>>>shamt; end end
    else exe_data=64'b0;
    /*
    case(exe_s1)
    3'b000:begin exe_data=e_op1+{{52{exe_i_imm[11]}},exe_i_imm};end//addi
    3'b010:exe_data=($signed(e_op1)<$signed({{52{exe_i_imm[11]}},exe_i_imm}))?1:0;//slit 
    3'b011:exe_data=($unsigned(e_op1)<$unsigned({{52{exe_i_imm[11]}},exe_i_imm}))?1:0;//slitu
    3'b100:exe_data=e_op1^{{52{exe_i_imm[11]}},exe_i_imm};//xori
    3'b110:exe_data=e_op1|{{52{exe_i_imm[11]}},exe_i_imm};//ori
    3'b111:exe_data=e_op1&{{52{exe_i_imm[11]}},exe_i_imm};//andi
    3'b001:exe_data=e_op1<<shamt;//slli
    3'b101:
    if(exe_s2==0)
    begin
      exe_data=e_op1>>shamt;//srli
    end
    else
    begin
      exe_data=($signed(e_op1))>>>shamt;//srai
    end
    default:exe_data=64'b0;
    endcase
    */
  end
  else if(exe_opcode==7'b1100011)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    exe_data=64'b0;
    //imm1=exe_b_imm[6];
    //imm5=exe_b_imm[5:0];
    //imm3=exe_b_imm_b[0];
    //imm6=exe_b_imm_b[4:1];
    //exe_b_imm_b_b={imm1,imm3,imm5,imm6};
    //exe_b_imm_b_b_b={{52{exe_b_imm_b_b[11]}},exe_b_imm_b_b};
    //exe_b_imm_b_b_b=exe_b_imm_b_b_b<<1;
    if(exe_s1==3'b000) begin  exe_pc_add=(e_op1==e_op2)?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=(e_op1==e_op2)?1:0; end//beq
    else if(exe_s1==3'b001) begin exe_pc_add=(e_op1!=e_op2)?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=(e_op1!=e_op2)?1:0; end//bne
    else if(exe_s1==3'b100) begin exe_pc_add=($signed(e_op1)<$signed(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($signed(e_op1)<$signed(e_op2))?1:0; end//blt
    else if(exe_s1==3'b101) begin exe_pc_add=($signed(e_op1)>=$signed(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($signed(e_op1)>=$signed(e_op2))?1:0; end
    else if(exe_s1==3'b110) begin  exe_pc_add=($unsigned(e_op1)<$unsigned(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($unsigned(e_op1)<$unsigned(e_op2))?1:0; end
    else if(exe_s1==3'b111) begin exe_pc_add=($unsigned(e_op1)>=$unsigned(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($unsigned(e_op1)>=$unsigned(e_op2))?1:0; end
    else begin exe_pc_add=64'b0;exe_pc_write=1'b0; end
    /*
    case(exe_s1)
    3'b000:begin
    exe_pc_add=(e_op1==e_op2)?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=(e_op1==e_op2)?1:0;
    end//beq
    3'b001:begin
    exe_pc_add=(e_op1!=e_op2)?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=(e_op1!=e_op2)?1:0;
    end//bne
    3'b100:begin
    exe_pc_add=($signed(e_op1)<$signed(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($signed(e_op1)<$signed(e_op2))?1:0;
    end//blt
    3'b101:begin
    exe_pc_add=($signed(e_op1)>=$signed(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($signed(e_op1)>=$signed(e_op2))?1:0;
    end//bge
    3'b110:begin
    exe_pc_add=($unsigned(e_op1)<$unsigned(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($unsigned(e_op1)<$unsigned(e_op2))?1:0;
    end//bltu
    3'b111:begin
    exe_pc_add=($unsigned(e_op1)>=$unsigned(e_op2))?exe_b_imm_b_b_b+exe_pc:exe_pc+4;
    exe_pc_write=($unsigned(e_op1)>=$unsigned(e_op2))?1:0;
    end//bgeu
    default:begin exe_pc_add=64'b0;exe_pc_write=1'b0; end
    endcase
    */
  end
  else if(exe_opcode==7'b0110111)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    //exe_u_imm_u={{44{exe_u_imm[19]}},exe_u_imm};
    //exe_u_imm_u=exe_u_imm_u<<12;
    exe_data=exe_u_imm_u;//lui
  end
  else if(exe_opcode==7'b0010111)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    //exe_u_imm_u={{44{exe_u_imm[19]}},exe_u_imm};
    //exe_u_imm_u=exe_u_imm_u<<12;
    exe_data=exe_u_imm_u+exe_pc;//auiexe_pc
  end
  else if(exe_opcode==7'b1101111)
  begin
    exe_csr_data=64'b0;
    exe_data=exe_pc+4;
    //imm1=exe_j_imm[8];
    //imm2=exe_j_imm[7:0];
    //imm3=exe_j_imm[19];
    //imm4=exe_j_imm[18:0];
    //jal_imm={imm3,imm2,imm1,imm4};
    //jal_imm=jal_imm<<1;
    exe_pc_add={{44{jal_imm[19]}},jal_imm}+exe_pc;
    exe_pc_write=1'b1;//jal
  end
  else if(exe_opcode==7'b1100111)
  begin
    exe_csr_data=64'b0;
    exe_data=exe_pc+4;
    exe_pc_add=e_op1+{{52{exe_j_imm_j[11]}},exe_j_imm_j};//&(~1);
    //if(exe_pc_add[0]==1'b1)
    //begin
      //exe_pc_add[0]=1'b0;
    //end
    exe_pc_write=1'b1;//jalr
  end
  else if(exe_opcode==7'b0011011)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    exe_data=64'b0;
    if(exe_s1==3'b000) begin //exe_data_w_add=e_op1+{{52{exe_w_imm[11]}},exe_w_imm};
    exe_data={{32{exe_data_w_add[31]}},exe_data_w_add[31:0]};end//addiw
    else if(exe_s1==3'b101) begin if(exe_s2==1'b0) begin exe_data={{32{srlw[31]}},srlw};end//srliw
    else begin exe_data={{32{sraw[31]}},sraw[31:0]}; end end//sraiw
    else if(exe_s1==3'b001) begin 
    exe_data={{32{exe_data_w_slli[31]}},exe_data_w_slli[31:0]};end//slliw
    else exe_data=64'b0;
    /*
    case(exe_s1)
    3'b000:
    begin
      exe_data_w=e_op1+{{52{exe_w_imm[11]}},exe_w_imm};
      exe_data={{32{exe_data_w[31]}},exe_data_w[31:0]};//addiw
    end
    3'b101:
    begin
      if(exe_s2==1'b0)
      begin
        srlw=e_op1[31:0];
        srlw=srlw>>exe_w_shamt;
        exe_data={{32{srlw[31]}},srlw};//srliw
      end
      else
      begin
        sraw=e_op1[31:0];
        sraw=($signed(sraw))>>>exe_w_shamt;
        exe_data={{32{sraw[31]}},sraw[31:0]};//sraiw
      end
    end
    3'b001:
    begin
      exe_data_w=e_op1<<exe_w_shamt;
      exe_data={{32{exe_data_w[31]}},exe_data_w[31:0]};//slliw
    end
    default:exe_data=64'b0;
    endcase
    */
  end
  else if(exe_opcode==7'b0111011)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    exe_data=64'b0;
    if(exe_s2==1'b0) begin
      if(exe_s1==3'b000) begin exe_data={{32{exe_data_addw[31]}},exe_data_addw[31:0]}; end//addw
      else if(exe_s1==3'b001) begin exe_data={{32{sllw[31]}},sllw[31:0]}; end//sllw
      else if(exe_s1==3'b101) begin exe_data={{32{srlw[31]}},srlw};end//srlw
      else exe_data=64'b0;
      /*
      case(exe_s1)
      3'b000:
      begin
        exe_data_w=e_op1+e_op2;
        exe_data={{32{exe_data_w[31]}},exe_data_w[31:0]};//addw
      end
      3'b001:
      begin
        sll_imm=e_op2[4:0];
        sllw=e_op1<<sll_imm;
        exe_data={{32{sllw[31]}},sllw[31:0]};//sllw
      end
      3'b101:
      begin
        srl_imm_w=e_op2[4:0];
        srlw=e_op1[31:0];
        srlw=srlw>>srl_imm_w;
        exe_data={{32{srlw[31]}},srlw};//srlw
      end
      default:exe_data=64'b0;
      endcase
      */
    end
    else begin
      if(exe_s1==3'b000) begin exe_data={{32{exe_data_w_sub[31]}},exe_data_w_sub[31:0]};end//subw
      else if(exe_s1==3'b101) begin exe_data={{32{sraw[31]}},sraw[31:0]};end //sraw
      else exe_data=64'b0;
      /*
      case(exe_s1)
      3'b000:
      begin
        exe_data_w=e_op1-e_op2;
        exe_data={{32{exe_data_w[31]}},exe_data_w[31:0]};//subw
      end
      3'b101:
      begin
        sraw=e_op1[31:0];//sraw
        sra_imm_w=e_op2[4:0];
        sraw=($signed(sraw))>>>sra_imm_w;
        exe_data={{32{sraw[31]}},sraw[31:0]};
      end
      default:exe_data=64'b0;
      endcase
      */
    end
  end
  else if(exe_opcode==7'b0001111)
  begin
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
    exe_data=64'b0;
    //exe_mem_bubble=1'b1;
  end
  else if(exe_opcode==7'b1110011)
  begin
     exe_pc_write=1'b0;
     exe_pc_add=64'b0;
     exe_csr_data=64'b0;
     exe_data=exe_t;
     //csr_zimm={{59{1'b0}},exe_zimm[4:0]};
     if(exe_s1==3'b001) exe_csr_data=e_op1;
     else if(exe_s1==3'b010) exe_csr_data=exe_t|e_op1;
     else if(exe_s1==3'b011) exe_csr_data=(exe_t)&(~e_op1);
     else if(exe_s1==3'b101) exe_csr_data=csr_zimm;
     else if(exe_s1==3'b110) exe_csr_data=exe_t|csr_zimm;
     else if(exe_s1==3'b111) exe_csr_data=(exe_t)&(~csr_zimm);
     else exe_csr_data=64'b0;
     /*
    case(exe_s1)
    3'b001:exe_csr_data=e_op1;
    3'b010:exe_csr_data=exe_t|e_op1;
    3'b011:exe_csr_data=(exe_t)&(~e_op1);
    3'b101:exe_csr_data=csr_zimm;
    3'b110:exe_csr_data=exe_t|csr_zimm;
    3'b111:exe_csr_data=(exe_t)&(~csr_zimm);
    default:exe_csr_data=64'b0;
    endcase   
    */
  end
  else
  begin
    //exe_mem_bubble=1'b0;
    exe_data=64'b0;
    exe_pc_write=1'b0;
    exe_pc_add=64'b0;
    exe_csr_data=64'b0;
  end
 //end
end
end

wire mem_read_open=(exe_mem_read)?((mem_mem_read)?0:1):0;
wire [63:0] exe_mem_read_addr;
assign exe_mem_read_addr=e_op1+{{52{exe_I_imm[11]}},exe_I_imm};
always @(posedge clk) begin
  if(rst)
  begin
    mem_read<=1'b0;
    s3<=3'b0;
  end
  else
  begin
  if(mem_read_open)
  begin
    mem_read<=1'b1;
    s3<=exe_mem_read_addr[2:0];
  end
  else if(r_hs&&axi_r_id_i==4'b0010)
  begin
    mem_read<=1'b0;
  end
  else
  begin
    mem_read<=mem_read;
    s3<=s3;
  end
  end
end
endmodule




  module ysyx_210448_ID_EXE (
    input clk,
    input wire rst,
    input wire id_fetched,
    input wire id_exe_en,
    input wire id_mem_read,
    input wire id_exe_bubble,
    input wire id_w_ena,
    input wire [63:0] id_pc,
    input wire [31:0] id_inst,
    input wire [63:0] id_op1,
    input wire [63:0] id_op2,
    input wire [63:0] id_t,
    input wire [4 : 0]id_rd,
    input wire [6:0] id_opcode,
    input wire [19 : 0]id_u_imm,
    input wire [19 : 0]id_j_imm,
    input wire [11 : 0]id_j_imm_j,
    input wire [11 : 0]id_i_imm, 
    input wire [11 : 0]id_I_imm,
    input wire [6 : 0]id_b_imm,
    input wire [6 : 0]id_s_imm,
    input wire [4 : 0]id_s_imm_s,
    input wire [4 : 0]id_b_imm_b,
    input wire [11:0]id_w_imm,
    input wire [5:0]id_w_shamt,
    input wire [2:0] id_s1,
    input wire id_s2,
    input wire [5:0]id_shamt,
    input wire [11:0]id_csr,
    input wire [4:0]id_zimm,
    //input wire id_csr_read,
    input wire id_csr_write,

    output reg [63:0] exe_pc,
    output reg [31:0] exe_inst,
    output reg exe_fetched,
    output reg exe_mem_read,
    output reg exe_w_ena,
    output reg [63:0] exe_op1,
    output reg [63:0] exe_op2,
    output reg [63:0] exe_t,
    output reg [4 : 0]exe_rd,
    output reg [6:0] exe_opcode,
    output reg [19 : 0]exe_u_imm,
    output reg [19 : 0]exe_j_imm,
    output reg [11 : 0]exe_j_imm_j,
    output reg [11 : 0]exe_i_imm, 
    output reg [11 : 0]exe_I_imm,
    output reg [6 : 0]exe_b_imm,
    output reg [6 : 0]exe_s_imm,
    output reg [4 : 0]exe_s_imm_s,
    //output reg [4 : 0]exe_i_imm_i,
    output reg [4 : 0]exe_b_imm_b,
    output reg [11:0]exe_w_imm,
    output reg [5:0]exe_w_shamt,
    output reg [2:0] exe_s1,
    output reg exe_s2,
    output reg [5:0]exe_shamt,
    output reg [11:0]exe_csr,
    output reg [4:0]exe_zimm,
    //output reg exe_csr_read,
    output reg exe_csr_write
  );

      always @(posedge clk) begin
        if(rst==1'b1)
        begin
        exe_pc<=64'b0;
        exe_inst<=32'b0;
        exe_op1<=64'b0;
        exe_op2<=64'b0;
        exe_t<=64'b0;
        exe_rd<=5'b0;
        exe_opcode<=7'b0;
        exe_u_imm<=20'b0;
        exe_j_imm<=20'b0;
        exe_j_imm_j<=12'b0;
        exe_i_imm<=12'b0;
        exe_I_imm<=12'b0;
        exe_b_imm<=7'b0;
        exe_s_imm<=7'b0;
        exe_s_imm_s<=5'b0;
        //exe_i_imm_i<=5'b0;
        exe_b_imm_b<=5'b0;
        exe_w_imm<=12'b0;
        exe_w_shamt<=6'b0;
        exe_s1<=3'b0;
        exe_s2<=1'b0;
        exe_shamt<=6'b0;
        exe_csr<=12'b0;
        exe_zimm<=5'b0;
        exe_mem_read<=1'b0;
        //exe_csr_read<=1'b0;
        exe_csr_write<=1'b0;
        exe_fetched<=1'b0;
        exe_w_ena<=1'b0;
        end
        else if(id_exe_en)
        begin
          if(id_exe_bubble==1'b1)
          begin
            exe_pc<=64'b0;
            exe_inst<=32'b0;
            exe_op1<=64'b0;
            exe_op2<=64'b0;
            exe_t<=64'b0;
            exe_rd<=5'b0;
            exe_opcode<=7'b0;
            exe_u_imm<=20'b0;
            exe_j_imm<=20'b0;
            exe_j_imm_j<=12'b0;
            exe_i_imm<=12'b0;
            exe_I_imm<=12'b0;
            exe_b_imm<=7'b0;
            exe_s_imm<=7'b0;
            exe_s_imm_s<=5'b0;
            //exe_i_imm_i<=5'b0;
            exe_b_imm_b<=5'b0;
            exe_w_imm<=12'b0;
            exe_w_shamt<=6'b0;
            exe_s1<=3'b0;
            exe_s2<=1'b0;
            exe_shamt<=6'b0;
            exe_csr<=12'b0;
            exe_zimm<=5'b0;
            exe_mem_read<=1'b0;
            //exe_csr_read<=1'b0;
            exe_csr_write<=1'b0;
            exe_fetched<=1'b0;
            exe_w_ena<=1'b0;
          end
          else
          begin
            exe_pc<=id_pc;
            exe_inst<=id_inst;
            exe_op1<=id_op1;
            exe_op2<=id_op2;
            exe_t<=id_t;
            exe_rd<=id_rd;
            exe_opcode<=id_opcode;
            exe_u_imm<=id_u_imm;
            exe_j_imm<=id_j_imm;
            exe_j_imm_j<=id_j_imm_j;
            exe_I_imm<=id_I_imm;
            exe_b_imm<=id_b_imm;
            exe_b_imm_b<=id_b_imm_b;
            exe_s_imm<=id_s_imm;
            exe_s_imm_s<=id_s_imm_s;
            exe_i_imm<=id_i_imm;
            exe_b_imm<=id_b_imm;
            exe_w_imm<=id_w_imm;
            exe_w_shamt<=id_w_shamt;
            exe_s1<=id_s1;
            exe_s2<=id_s2;
            exe_shamt<=id_shamt;
            exe_csr<=id_csr;
            exe_zimm<=id_zimm;
            exe_mem_read<=id_mem_read;
            //exe_csr_read<=id_csr_read;
            exe_csr_write<=id_csr_write;
            exe_fetched<=id_fetched;
            exe_w_ena<=id_w_ena;
          end
        
    end
      end
  endmodule
  


module ysyx_210448_id_stage(
  input wire [31 : 0]id_inst,
  output wire [4 : 0]id_rd,
  output wire [6:0] id_opcode,
  output wire [19 : 0]id_u_imm,
  output wire [19 : 0]id_j_imm,
  output wire [11 : 0]id_j_imm_j,
  output wire [11 : 0]id_i_imm,
  output wire [11 : 0]id_I_imm,
  output wire [6 : 0]id_b_imm,
  output wire [6 : 0]id_s_imm,
  output wire [4 : 0]id_s_imm_s,
  output wire [4 : 0]id_b_imm_b,
  output wire [11:0]id_w_imm,
  output wire [5:0]id_w_shamt,
  output wire [2:0] id_s1,
  output wire id_s2,
  output wire [5:0]id_shamt,
  output wire [11:0]id_csr,
  output wire [4:0]id_zimm,
  output wire id_csr_read,
  output wire id_csr_write,
  output wire [4:0] id_rs1,
  output wire [4:0] id_rs2,
  output wire id_ena1,
  output wire id_ena2,
  output wire id_exe_en
);

//rs1,rs2为寄存器的编号，ena1,en2为对应的寄存器读信号，rd是写寄存器编号，s1为判断具体的指令，s2作用同上，其余带imm均为立即数

assign id_exe_en=1'b1;
assign id_opcode=id_inst[6 : 0];
assign id_rs1=(id_opcode==7'b1100111|id_opcode==7'b0000011|id_opcode==7'b0010011|id_opcode==7'b1100011|id_opcode==7'b0100011|id_opcode==7'b0110011|id_opcode==7'b0011011|id_opcode==7'b0111011|id_opcode==7'b1110011)?id_inst[19:15]:((id_opcode==7'b1111011)?5'h0a:0);
assign id_rs2=(id_opcode==7'b1100011|id_opcode==7'b0100011|id_opcode==7'b0110011|id_opcode==7'b0111011)?id_inst[24:20]:0;
assign id_ena1=(id_opcode==7'b1100111|id_opcode==7'b0000011|id_opcode==7'b0010011|id_opcode==7'b1100011|id_opcode==7'b0100011|id_opcode==7'b0110011|id_opcode==7'b0011011|id_opcode==7'b0111011|id_opcode==7'b1111011|id_opcode==7'b1110011)?1:0;
assign id_ena2=(id_opcode==7'b1100011|id_opcode==7'b0100011|id_opcode==7'b0110011|id_opcode==7'b0111011)?1:0;
assign id_rd=(id_opcode==7'b0110111|id_opcode==7'b0010111|id_opcode==7'b1101111|id_opcode==7'b0000011|id_opcode==7'b0010011|id_opcode==7'b0110011|id_opcode==7'b1100111|id_opcode==7'b0011011|id_opcode==7'b0111011|id_opcode==7'b1110011)?id_inst[11:7]:0;
assign id_s1=(id_opcode==7'b0000011|id_opcode==7'b0010011|id_opcode==7'b1100011|id_opcode==7'b0100011|id_opcode==7'b0110011|id_opcode==7'b0111011|id_opcode==7'b0011011|id_opcode==7'b1110011)?id_inst[14:12]:0;
assign id_s2=(id_opcode==7'b0010011|id_opcode==7'b0110011|id_opcode==7'b0111011|id_opcode==7'b0011011)?id_inst[30]:0;
assign id_u_imm=(id_opcode==7'b0110111|id_opcode==7'b0010111)?id_inst[31:12]:0;
assign id_j_imm=(id_opcode==7'b1101111)?id_inst[31:12]:0;
assign id_j_imm_j=(id_opcode==7'b1100111)?id_inst[31:20]:0;
assign id_I_imm=(id_opcode==7'b0000011)?id_inst[31:20]:0;
assign id_i_imm=(id_opcode==7'b0010011)?id_inst[31:20]:0;
assign id_shamt=(id_opcode==7'b0010011)?id_inst[25:20]:0;
assign id_b_imm=(id_opcode==7'b1100011)?id_inst[31:25]:0;
assign id_b_imm_b=(id_opcode==7'b1100011)?id_inst[11:7]:0;
assign id_s_imm=(id_opcode==7'b0100011)?id_inst[31:25]:0;
assign id_s_imm_s=(id_opcode==7'b0100011)?id_inst[11:7]:0;
assign id_w_imm=(id_opcode==7'b0011011)?id_inst[31:20]:0;
assign id_w_shamt=(id_opcode==7'b0011011)?id_inst[25:20]:0;
assign id_csr=(id_opcode==7'b1110011)?id_inst[31:20]:0;
assign id_zimm=(id_opcode==7'b1110011)?id_inst[19:15]:0;
assign id_csr_read=(id_opcode==7'b1110011)?1:0;
assign id_csr_write=(id_opcode==7'b1110011)?1:0;

endmodule


module ysyx_210448_IF_ID (
  input wire clk,
  input wire rst,
  input wire if_id_en,
  input wire if_id_bubble,
  input wire if_mem_read,
  input wire [63 : 0] if_pc,
  input wire [31 : 0] if_inst,
  input wire if_w_ena,
  input wire if_fetched,
  output reg [63 : 0] id_pc,
  output reg id_mem_read,
  output reg [31 : 0] id_inst,
  output reg id_w_ena,
  output reg id_fetched
 
);
//bubble 气泡，清空寄存器
    always @(posedge clk) begin

        if(rst==1'b1)
        begin
            id_pc<=64'b0;
            id_inst<=32'b0;
            id_fetched<=1'b0;
            id_mem_read<=1'b0;
            id_w_ena<=1'b0;
        end
        else if(if_id_en)
        begin
            if(if_id_bubble==1'b1)
            begin
            id_pc<=64'b0;
            id_inst<=32'b0;
            id_fetched<=1'b0;
            id_mem_read<=1'b0;
            id_w_ena<=1'b0;
            end
            else
            begin
            id_inst<=if_inst;
            id_pc<=if_pc;
            id_fetched<=if_fetched;  
            id_mem_read<=if_mem_read;
            id_w_ena<=if_w_ena;
            end
        end
    end
    

endmodule


module ysyx_210448_if_stage(
  input wire clk,
  input wire rst,
  input wire stop,
  input wire if_ready,
  input wire r_hs,
  input wire b_hs,
  input wire mem_write,
  input wire [63:0] if_data_read,
  input wire [63:0]pc_add,
  input wire pc_write,
  output reg [63 : 0] if_pc,
  output reg [31 : 0] if_inst,
  output wire if_id_en,
	output wire if_valid,
  output reg [63:0] if_addr,
  output reg if_fetched,
  output wire [3:0] if_read_id,
  output reg if_mem_read,
  output wire if_w_ena,
  output wire if_ar_hand,
  output wire axi_mem_read,
  output wire axi_mem_write
);
assign if_id_en=1'b1;
assign if_ar_hand=(if_valid)&&(if_ready);
wire [63:0] if_inst_data;
assign if_read_id=4'b0010;
//对于跳转取到错误的值将其清除
assign if_inst_data=((pc_write==1'b1)&&(if_inst!=32'b0))?64'b0:if_data_read;
//wire write_wait=(mem_write)?((b_hs)?1'b0:1'b1):1'b0;
reg if_stage;
reg write_ok;

always @(posedge clk) begin
  if(rst)
  begin
    write_ok<=1'b0;
  end
  else
  begin
  if(b_hs)
  write_ok<=1'b1;
  else if(if_fetched)
  write_ok<=1'b0;
  end
end
always @(*) begin
  if(rst)
  begin
    if_stage=1'b0;
  end
  else begin
  if(if_ready&&(~stop))
  begin
    if(axi_mem_write)
    begin
      if(write_ok)
      if_stage=1'b1;
      else
      if_stage=1'b0;
    end
    else
    if_stage=1'b1;
  end
  else
  if_stage=1'b0;
  end
end

always @( posedge clk ) begin
  if (rst) begin
    if_pc <= 64'h3000_0000;
    if_addr <=64'h3000_0000;
    if_fetched <= 1'b0;
    if_inst<=32'b0;
    if_mem_read<=1'b0;
  end
  else if (if_stage) begin//&&(~write_wait)
    if_mem_read<=(if_inst_data[6:0]==7'b0000011)?1:0;
    if((pc_write==1'b1)&&(if_inst!=32'h0)) begin
    if_pc<=pc_add;
    if_addr<=pc_add;
    if_fetched<=1; 
    if_inst<=if_inst_data[31:0];
    end
    else begin
    if_pc<=if_addr;
    if_addr<=if_addr + 4;
    if_fetched<= 1;
    if_inst<=if_inst_data[31:0];
    end
  end
  else if(r_hs)
  begin
    if_mem_read<=1'b0;
  end
  else begin
    if_fetched <= 0;
  end
end

reg if_valid_wait;
always @(posedge clk) begin
  if(rst)
  begin
    if_valid_wait<=1'b0;
  end
  else
  begin
  if(mem_write)
  if_valid_wait<=1'b1;
  else if(r_hs)
  if_valid_wait<=1'b1;
  else
  if_valid_wait<=1'b0;
  end
end

assign if_valid =(axi_mem_write)?((if_valid_wait)?1'b0:1'b1):1'b1;//
assign axi_mem_read=(if_inst[6:0]==7'b0000011)?1:0;
assign axi_mem_write=(if_inst[6:0]==7'b0100011)?1:0;
assign if_w_ena=((if_inst[6:0]==7'b1100011)||(if_inst[6:0]==7'b0000011)||(if_inst[6:0]==7'b0100011))?0:1;//寄存器使能信号

endmodule


`timescale 1ns / 1ps



module ysyx_210448_mem_stage (
    input clk,
    input wire rst,
    input wire axi_mem_write,
    input wire mem_fetched,
    input wire [2:0]s3,
    input wire [6:0]mem_opcode,
    input wire [6 : 0]mem_s_imm,
    input wire [4 : 0]mem_s_imm_s,
    input wire [63:0]mem_op1,
    input wire [63:0]mem_op2,
    input wire [11:0] mem_I_imm,
    input wire [2:0] mem_s1,
    output reg mem_write,
    input wire wb_write_ready,
    input wire b_hs,
    //output reg [1:0] axi_size,
    output wire [63:0] mem_read_addr,
    input wire [63:0] rdata,
    output wire [63:0] mem_write_addr,
    output reg [63:0] wdata,
    output reg [7:0] wmask,
    output wire mem_write_ready,
    output reg[63:0] mem_read_data,
    //input wire mem_wb_en,
    output wire [3:0]mem_read_id
    
);
wire [11:0]s_s;
wire [63:0] mem_data;
//wire mem_write_ready;
assign mem_read_id=4'b0001;
//判断取的是哪个字节
wire [2:0] s4;
//wire [2:0] s3;
//预处理写的值，读的地址
//把exe阶段的处理到这里
//单周期时总是慢一拍，猜测是exe阶段延时
assign mem_write_ready=(axi_mem_write&&mem_fetched)?((wb_write_ready)?0:1):0;
/*assign mem_write_ready=((mem_write_addr==64'h2004000)||(mem_write_addr==64'h200bff8))?
                       0:((axi_mem_write&&mem_fetched)?((wb_write_ready)?0:1):0);
                       */
assign s4=mem_write_addr[2:0];
//reg [11:0] mem_I_imm_I;
assign mem_read_addr=mem_op1+{{52{mem_I_imm[11]}},mem_I_imm};
assign mem_write_addr=mem_op1+{{52{s_s[11]}},s_s};
assign s_s={mem_s_imm,mem_s_imm_s};
assign mem_data=mem_op2;

always @(posedge clk) begin
  if(rst)
  begin
    mem_write<=1'b0;
  end
  else
  begin
  if(mem_write_ready)
  begin
    mem_write<=1'b1;
  end
  else if(b_hs)
  begin
    mem_write<=1'b0;
  end
  else
  begin
    mem_write<=mem_write;
  end
  end
end



always@(*) begin
  if(rst)
  begin
    //axi_size=2'b0;
    wdata=64'b0;
    wmask=8'b0;
    mem_read_data=64'b0;
  end
  else begin
if(mem_opcode==7'b0000011)
begin
    mem_read_data=`YSYX210448_ZERO_WORD;
        if(mem_s1==3'b000)//lb
        begin
          if(s3==3'b000) begin
          mem_read_data={{56{rdata[7]}},rdata[7:0]}; end
          else if(s3==3'b001) begin
          mem_read_data={{56{rdata[15]}},rdata[15:8]}; end
          else if(s3==3'b010) begin
          mem_read_data={{56{rdata[23]}},rdata[23:16]}; end
          else if(s3==3'b011) begin
          mem_read_data={{56{rdata[31]}},rdata[31:24]}; end
          else if(s3==3'b100) begin
          mem_read_data={{56{rdata[39]}},rdata[39:32]}; end
          else if(s3==3'b101) begin
          mem_read_data={{56{rdata[47]}},rdata[47:40]}; end
          else if(s3==3'b110) begin
          mem_read_data={{56{rdata[55]}},rdata[55:48]}; end
          else if(s3==3'b111) begin
          mem_read_data={{56{rdata[63]}},rdata[63:56]}; end
        end
        else if(mem_s1==3'b001)//lh
        begin
          if(s3==3'b000) begin
          mem_read_data={{48{rdata[15]}},rdata[15:0]}; end
          else if(s3==3'b010) begin
          mem_read_data={{48{rdata[31]}},rdata[31:16]}; end
          else if(s3==3'b100) begin
          mem_read_data={{48{rdata[47]}},rdata[47:32]}; end
          else if(s3==3'b110) begin
          mem_read_data={{48{rdata[63]}},rdata[63:48]}; end
        end
        else if(mem_s1==3'b010)
        begin
          if(s3==3'b000) begin
          mem_read_data={{32{rdata[31]}},rdata[31:0]}; end
          else if(s3==3'b100) begin
          mem_read_data={{32{rdata[63]}},rdata[63:32]}; end//lw
        end
        else if(mem_s1==3'b110)
        begin
          if(s3==3'b000) begin
          mem_read_data={{32{1'b0}},rdata[31:0]}; end
          else if(s3==3'b100) begin
          mem_read_data={{32{1'b0}},rdata[63:32]}; end//lwu
        end
        else if(mem_s1==3'b100)//lbu
        begin
          if(s3==3'b000) begin
          mem_read_data={{56{1'b0}},rdata[7:0]}; end
          else if(s3==3'b001) begin
          mem_read_data={{56{1'b0}},rdata[15:8]}; end
          else if(s3==3'b010) begin
          mem_read_data={{56{1'b0}},rdata[23:16]}; end
          else if(s3==3'b011) begin
          mem_read_data={{56{1'b0}},rdata[31:24]}; end
          else if(s3==3'b100) begin
          mem_read_data={{56{1'b0}},rdata[39:32]}; end
          else if(s3==3'b101) begin
          mem_read_data={{56{1'b0}},rdata[47:40]}; end
          else if(s3==3'b110) begin
          mem_read_data={{56{1'b0}},rdata[55:48]}; end
          else if(s3==3'b111) begin
          mem_read_data={{56{1'b0}},rdata[63:56]}; end
        end
        else if(mem_s1==3'b101)////lhu
        begin
          if(s3==3'b000) begin
          mem_read_data={{48{1'b0}},rdata[15:0]}; end
          else if(s3==3'b010) begin
          mem_read_data={{48{1'b0}},rdata[31:16]}; end
          else if(s3==3'b100) begin
          mem_read_data={{48{1'b0}},rdata[47:32]}; end
          else if(s3==3'b110|s3==3'b000) begin
          mem_read_data={{48{1'b0}},rdata[63:48]}; end
        end
        else if(mem_s1==3'b011)
        begin
          mem_read_data=rdata;
        end
        else
        begin
          mem_read_data=`YSYX210448_ZERO_WORD;
        end
end  
else begin
mem_read_data=`YSYX210448_ZERO_WORD;
end
if(mem_opcode==7'b0100011)
begin
      wdata=`YSYX210448_ZERO_WORD;  
      if(mem_s1==3'b000)///sb
      begin
      wdata={8{mem_data[7:0]}};
      //axi_size=mem_s1[1:0];
      if(s4==3'b000)begin
      wmask=8'b00000001;end
      else if(s4==3'b001)begin
      wmask=8'b00000010;end
      else if(s4==3'b010) begin
      wmask=8'b00000100;end
      else if(s4==3'b011) begin
      wmask=8'b00001000;end
      else if(s4==3'b100) begin
      wmask=8'b00010000;end
      else if(s4==3'b101) begin
      wmask=8'b00100000;end
      else if(s4==3'b110) begin
      wmask=8'b01000000;end
      else if(s4==3'b111) begin
      wmask=8'b10000000;end
      else begin
        wmask=`YSYX210448_ZERO_8;
      end
      end
      else if(mem_s1==3'b001)//sh
      begin
      wdata={4{mem_data[15:0]}};
      //axi_size=mem_s1[1:0];
      if(s4==3'b000) begin
      wmask=8'b00000011; end
      else if(s4==3'b010) begin
      wmask=8'b00001100; end
      else if(s4==3'b100) begin
      wmask=8'b00110000;end
      else if(s4==3'b110) begin
      wmask=8'b11000000; end
      else begin
        wmask=`YSYX210448_ZERO_8;
      end
      end
      else if(mem_s1==3'b010)//sw
      begin
      wdata={2{mem_data[31:0]}};
      //axi_size=mem_s1[1:0];
      if(s4==3'b000) begin
      wmask=8'b00001111; end
      else if(s4==3'b100) begin
      wmask=8'b11110000; end
      else begin
        wmask=`YSYX210448_ZERO_8;
      end
      end
      else if(mem_s1==3'b011)//sd
      begin
        wdata=mem_data[63:0];
        //axi_size=mem_s1[1:0];
        wmask=8'b11111111;
      end
      else
      begin
      wdata=`YSYX210448_ZERO_WORD;
      wmask=`YSYX210448_ZERO_8;
      //axi_size=`YSYX210448_SIZE_W;
      end
end
else
begin
  wdata=`YSYX210448_ZERO_WORD;
  wmask=`YSYX210448_ZERO_8;
  //axi_size=`YSYX210448_SIZE_W;
end
end
end




endmodule




module ysyx_210448_MEM_WB (
    input clk,
    input wire rst,
    input wire mem_wb_en,
    //input wire mem_write,
    input wire mem_write_ready,
    input wire [63:0]mem_pc,
    input wire [31:0] mem_inst,
    input wire mem_fetched,
    input wire mem_w_ena,
	  input wire [4:0] mem_rd,
	  input wire [`YSYX210448_REG_BUS] mem_data,
    input wire mem_read,
    input wire [63:0]mem_read_data,
    input wire [11:0]mem_csr,
    input wire mem_csr_write,
	  //input wire mem_csr_read,
    input wire [63:0] mem_csr_data,

    output reg [63:0]wb_pc,
    output reg [31:0] wb_inst,
    output reg wb_fetched,
    output reg wb_write_ready,
    output reg wb_w_ena,
    //output reg wb_write,
	  output reg [4:0] wb_rd,
	  output reg [`YSYX210448_REG_BUS] wb_data,
    output reg wb_read,
    output reg [63:0]wb_read_data,
    output reg [11:0]wb_csr,
    output reg wb_csr_write,
    output reg [63:0] wb_csr_data
);

    always @(posedge clk) begin
      if(rst==1'b1)
        begin
        wb_pc<=64'b0;
        wb_inst<=32'b0;
        wb_w_ena<=1'b0;
	      wb_rd<=5'b0;
	      wb_data<=64'b0;
        wb_read<=1'b1;
        wb_read_data<=64'b0;
        wb_csr<=12'b0;
        wb_csr_write<=1'b0;
        wb_csr_data<=64'b0;
        wb_fetched<=1'b0;
        //wb_write<=1'b0;
        wb_write_ready<=1'b0;
        end
        else if(mem_wb_en)
        begin
        wb_pc<=mem_pc;
        wb_inst<=mem_inst;
        wb_w_ena<=mem_w_ena;
	      wb_rd<=mem_rd;
	      wb_data<=mem_data;
        wb_read<=mem_read;
        wb_read_data<=mem_read_data;
        wb_csr<=mem_csr;
        wb_csr_write<=mem_csr_write;
        wb_csr_data<=mem_csr_data;
        wb_fetched<=mem_fetched;
        //wb_write<=mem_write;
        wb_write_ready<=mem_write_ready;
        end
    end
endmodule




//说明，以下模块实现了流水线的暂停，数据前递，插入气泡，注意下面有优先级关系，请谨慎修改
//数据冒险：相邻指令，隔一条指令均在下方实现，隔两条指令的处理在寄存器，解决均采用数据前递（旁路）的方法
//当相邻指令的上一条是load相关指令处理办法：暂停pc,IF_ID,在ID_EXE阶段插入气泡，等到进行的wb阶段将流水线开启，引入ld信号，避免将exe阶段的值传给op1,op2
//控制冒险：当pc要跳时，在IF_ID，ID_EXE阶段插入气泡


module ysyx_210448_pause (
    input clk,
    input wire rst,
    input wire if_fetched,
    input wire id_fetched,
    //input wire [63:0] exe_data,
    input wire [63:0] mem_data,
    input wire [63:0] wb_data,
    input wire [6:0] mem_opcode,
    input wire [6:0] exe_opcode,
    input wire [4:0] id_rs1,
    input wire [4:0] id_rs2,
    input wire [4:0] exe_rd,
    input wire [4:0] mem_rd,
    output reg [63:0] p_exe_op1,
    output reg [63:0] p_exe_op2,
    output reg p_ready1,
    output reg p_ready2,
    output wire ld
);
//wire ld;
assign ld=((mem_opcode==7'b0000011)||(exe_opcode==7'b0000011))?1:0;
always @(posedge clk) begin
    if(rst==1'b1)
    begin 
        p_exe_op1<=64'b0;
        p_ready1<=1'b0;
    end
    else if((~ld)&&(id_fetched))
    begin
        if((id_rs1==mem_rd)&&(id_rs1!=0)&&(mem_rd!=0)&&(mem_opcode!=7'b0000011)) 
        begin//隔一条指令
            p_exe_op1<=wb_data;
            p_ready1<=1'b1;
        end
        else if((id_rs1==exe_rd)&&(id_rs1!=0)&&(exe_rd!=0)&&(exe_opcode!=7'b0000011))
        begin  //相邻指令
            p_exe_op1<=mem_data;
            p_ready1<=1'b1;
        end
    end
    else if(if_fetched)
    begin
        p_exe_op1<=64'b0;
        p_ready1<=1'b0;
    end
   
end
always @(posedge clk) begin
    if(rst==1'b1)
    begin 
        p_exe_op2<=64'b0;
        p_ready2<=1'b0;
    end
    else if((~ld)&&(id_fetched))
    begin
        if((id_rs2==mem_rd)&&(id_rs2!=0)&&(mem_rd!=0)&&(mem_opcode!=7'b0000011))
        begin  //隔一条指令
            p_exe_op2<=wb_data;
            p_ready2<=1'b1;
        end
        else if((id_rs2==exe_rd)&&(id_rs2!=0)&&(exe_rd!=0)&&(exe_opcode!=7'b0000011))  
        begin//相邻指令
            p_exe_op2<=mem_data;
            p_ready2<=1'b1;
        end
    end
    else if(if_fetched)
    begin
        p_exe_op2<=64'b0;
        p_ready2<=1'b0;
    end
end



endmodule


module ysyx_210448_regfile(
  input wire clk,
	input wire rst,
	input wire read,
	input wire ld,
	input wire [63:0]read_data,
	input wire [4:0] w_addr,
	input wire [`YSYX210448_REG_BUS] data,
	input wire w_ena,
	input wire [4:0] rs1,
	input wire [4:0] rs2,
	input wire ena1,
	input wire ena2,
	output reg [`YSYX210448_REG_BUS] op1,
	output reg [`YSYX210448_REG_BUS] op2
    );
wire  [`YSYX210448_REG_BUS] w_data;
assign w_data=(read==1'b1)?read_data:data;//判断存的数据是从mem中取的还是exe的计算值
reg [`YSYX210448_REG_BUS] 	regs[0 : 31];
always @(posedge clk) 
	begin
		if (rst==1'b1) 
		begin
			regs[ 0] <= `YSYX210448_ZERO_WORD;
			regs[ 1] <= `YSYX210448_ZERO_WORD;
			regs[ 2] <= `YSYX210448_ZERO_WORD;
			regs[ 3] <= `YSYX210448_ZERO_WORD;
			regs[ 4] <= `YSYX210448_ZERO_WORD;
			regs[ 5] <= `YSYX210448_ZERO_WORD;
			regs[ 6] <= `YSYX210448_ZERO_WORD;
			regs[ 7] <= `YSYX210448_ZERO_WORD;
			regs[ 8] <= `YSYX210448_ZERO_WORD;
			regs[ 9] <= `YSYX210448_ZERO_WORD;
			regs[10] <= `YSYX210448_ZERO_WORD;
			regs[11] <= `YSYX210448_ZERO_WORD;
			regs[12] <= `YSYX210448_ZERO_WORD;
			regs[13] <= `YSYX210448_ZERO_WORD;
			regs[14] <= `YSYX210448_ZERO_WORD;
			regs[15] <= `YSYX210448_ZERO_WORD;
			regs[16] <= `YSYX210448_ZERO_WORD;
			regs[17] <= `YSYX210448_ZERO_WORD;
			regs[18] <= `YSYX210448_ZERO_WORD;
			regs[19] <= `YSYX210448_ZERO_WORD;
			regs[20] <= `YSYX210448_ZERO_WORD;
			regs[21] <= `YSYX210448_ZERO_WORD;
			regs[22] <= `YSYX210448_ZERO_WORD;
			regs[23] <= `YSYX210448_ZERO_WORD;
			regs[24] <= `YSYX210448_ZERO_WORD;
			regs[25] <= `YSYX210448_ZERO_WORD;
			regs[26] <= `YSYX210448_ZERO_WORD;
			regs[27] <= `YSYX210448_ZERO_WORD;
			regs[28] <= `YSYX210448_ZERO_WORD;
			regs[29] <= `YSYX210448_ZERO_WORD;
			regs[30] <= `YSYX210448_ZERO_WORD;
			regs[31] <= `YSYX210448_ZERO_WORD;
		end
		else 
		begin
			if (((w_ena==1'b1)|(read==1'b1)) && (w_addr!=5'h00))
			begin
				regs[w_addr] <=w_data;
			end
		end
	end

always @(*) begin
		if (rst == 1'b1)
			op1=`YSYX210448_ZERO_WORD;
		else  begin
    if (ena1 == 1'b1)
		begin
			op1=regs[rs1];
		end
		else if(ld)
		begin
			op1=regs[rs1];
		end
		else
			op1=`YSYX210448_ZERO_WORD;
    end
	end
	
always @(*) begin
	if (rst == 1'b1)
			op2=`YSYX210448_ZERO_WORD;
		else begin
    if (ena2 == 1'b1)
		begin
			op2=regs[rs2];
		end
		else if(ld)
		begin
			op2=regs[rs2];
		end
		else
			op2=`YSYX210448_ZERO_WORD;
	end
end

endmodule


module ysyx_210448_wb_stage (
  input wire clk,
  input wire rst,
  input wire ld,
  input wire [63:0] if_pc,
  input wire [31:0] wb_inst,
  input wire exe_pc_write,
  input wire [63:0] exe_pc_add,
  input wire id_ena1,
  input wire id_ena2,
  input wire if_fetched,
  input wire wb_fetched,
  //input wire exe_fetched,
  input wire mem_fetched,
  input wire exe_w_ena,
  input wire if_ar_hand,
  input wire axi_mem_read,
  input wire axi_mem_write,
  input [63:0] mtimecmp_data,
  input mtimecmp_open,
  input [63:0] mtime_data,
  input mtime_open,
  input wire [4:0] id_rs1,
  input wire [4:0] id_rs2,
  input wire if_w_ena,
  input wire [63:0]wb_pc,
  input wire wb_w_ena,
	input wire [4:0] wb_rd,
	input wire [`YSYX210448_REG_BUS] wb_data,
  input wire wb_read,
  input wire [63:0]wb_read_data,
  input wire [11:0]wb_csr,
  input wire [11:0] id_csr,
  input wire wb_csr_write,
	input wire id_csr_read,
  input wire [63:0] wb_csr_data,
  output wire [63:0] mtime,
  output wire [63:0] mtimecmp,
  output wire [63:0] id_op1,
  output wire [63:0] id_op2,
  output wire [63:0]id_t,
  output wire [63:0] csr_pc_add,
  output wire csr_pc_write//,
  //output wire ena1,
  //output wire ena2
);
wire ena1;
wire ena2;
wire w_ena;
wire [4:0] w_rd;
assign w_rd=(w_ena)?wb_rd:0;
//wire ena1;
assign ena1=(axi_mem_write)?((wb_rd==id_rs1)?((if_w_ena==1'b1)?0:id_ena1):id_ena1):((wb_rd==id_rs1)?((exe_w_ena==1'b1)?id_ena1:0):id_ena1);
assign ena2=(axi_mem_write)?((wb_rd==id_rs2)?((if_w_ena==1'b1)?0:id_ena2):id_ena2):((wb_rd==id_rs2)?((exe_w_ena==1'b1)?id_ena2:0):id_ena2);
//数据冒险结束的标志
assign w_ena=(axi_mem_read)?wb_read:wb_w_ena;

ysyx_210448_CSR ysyx_210448_CSR(
.clk(clk),
.rst(rst),
.if_pc(if_pc),
.wb_inst(wb_inst),
.if_ar_hand(if_ar_hand),
.exe_pc_write(exe_pc_write),
.exe_pc_add(exe_pc_add),
//.exe_fetched(exe_fetched),
.wb_csr(wb_csr),
.id_csr(id_csr),
.pc(wb_pc),
.wb_read(wb_read),
.if_fetched(if_fetched),
.wb_fetched(wb_fetched),
.mem_fetched(mem_fetched),
.wb_csr_write(wb_csr_write),
.id_csr_read(id_csr_read),
.csr_data(wb_csr_data),
.id_t(id_t),
.id_rs1(id_rs1),
.wb_rd(wb_rd),
.mtime(mtime),
.mtimecmp(mtimecmp),
.mtimecmp_data(mtimecmp_data),
.mtimecmp_open(mtimecmp_open),
.mtime_data(mtime_data),
.mtime_open(mtime_open),
.csr_pc_add(csr_pc_add),
.csr_pc_write(csr_pc_write)
);

  ysyx_210448_regfile ysyx_210448_Regfile(
  .clk(clk),
  .rst(rst),
  .ld(ld),
  .read(wb_read),//wb_read
  .read_data(wb_read_data),
  .w_addr(w_rd),
  .data(wb_data),
  .w_ena(w_ena),
  .rs1(id_rs1),
  .op1(id_op1),
  .ena1(ena1),
  .rs2(id_rs2),
  .op2(id_op2),
  .ena2(ena2)
);

endmodule
